Czy można ustawić kod za słownikiem zasobów w WPF do obsługi zdarzeń?


147

Czy można ustawić kod za słownikiem zasobów w WPF. Na przykład w kontrolce użytkownika dla przycisku deklarujesz go w języku XAML. Kod obsługi zdarzenia dla kliknięcia przycisku znajduje się w pliku kodu znajdującym się za formantem. Gdybym miał utworzyć szablon danych z przyciskiem, w jaki sposób mogę napisać kod obsługi zdarzeń dla jego kliknięcia przycisku w słowniku zasobów.


1
Prawidłowym sposobem na to jest użycie polecenia, które daje również możliwość włączania i wyłączania przycisku, podczas gdy możesz to zrobić w sposób, w jaki niektóre odpowiedzi sugerowały, że pachnie włamaniem.
Aran Mulholland

Odpowiedzi:


209

Myślę, że chcesz mieć plik związany z kodem dla ResourceDictionary. Możesz to zrobić całkowicie! W rzeczywistości robisz to tak samo, jak w przypadku okna:

Załóżmy, że masz ResourceDictionary o nazwie MyResourceDictionary. W pliku MyResourceDictionary.xaml umieść atrybut x: Class w elemencie głównym, na przykład:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="MyCompany.MyProject.MyResourceDictionary"
                    x:ClassModifier="public">

Następnie utwórz kod związany z plikiem o nazwie MyResourceDictionary.xaml.cs z następującą deklaracją:

namespace MyCompany.MyProject
{
    partial class MyResourceDictionary : ResourceDictionary
    { 
       public MyResourceDictionary()
       {
          InitializeComponent();
       }     
       ... // event handlers ahead..
    }
}

I jesteś skończony. Możesz umieścić w kodzie wszystko, co chcesz: metody, właściwości i programy obsługi zdarzeń.

== Aktualizacja dla aplikacji Windows 10 ==

Na wypadek, gdybyś grał z UWP , jest jeszcze jedna rzecz, o której należy pamiętać:

<Application x:Class="SampleProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:rd="using:MyCompany.MyProject">
<!-- no need in x:ClassModifier="public" in the header above -->

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- This will NOT work -->
                <!-- <ResourceDictionary Source="/MyResourceDictionary.xaml" />-->

                <!-- Create instance of your custom dictionary instead of the above source reference -->
                <rd:MyResourceDictionary />

            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

7
Jako dodatek do odpowiedzi ageektrapped: Upewnij się, że w atrybucie x: Class umieściłeś w pełni kwalifikowaną nazwę swojej klasy codebehind. x:Class="MyCompany.MyProject.MySubFolder1.MyResourceDictionary"W przeciwnym razie, jeśli po prostu wstawisz x: Class = "MyResourceDictionary", parser xaml nie znajdzie twojej klasy.
viggity

29
Upewnij się, że podałeś domyślny konstruktor w częściowej klasie codebehind i upewnij się, że wywołuje InitializeComponent (). (W moim przypadku użyłem MEF do wyeksportowania słownika zasobów.)
Scott Whitlock,

4
Zaktualizowano fragment kodu komentarza za głosem. Czułem, że trzeba uzupełnić odpowiedź; częsty błąd. Zrobiłem to przed chwilą :) Przywróć, jeśli ci się nie podoba. Dziękuję za odpowiedź.
Gishu

2
Zauważ, że (przynajmniej w wp8.1) nie jest to już ważne i musiałbyś utworzyć niestandardową kontrolę użytkownika, do której odwołuje się twój słownik zasobów
Jared

9
Będziesz także musiał ustawić akcję kompilacji w pliku XAML ResourceDictionary na „Page”, w przeciwnym razie wywołanie InitializeComponent () nie zostanie skompilowane. (Pliki ResourceDictionary XAML są zwykle domyślnie ustawione na „Zasób”).
user1454265

9

Nie zgadzam się z „ageektrapped”… stosowanie metody częściowej nie jest dobrą praktyką. Jaki byłby zatem cel oddzielenia Słownika od strony?

Z poziomu kodu można uzyskać dostęp do elementu ax: Name za pomocą:

Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
   ...
}

Można zrobić to w metodzie OnApplyTemplate jeśli chcesz hookup kontrolom Po wczytaniu kontroli zwyczaj. Aby to zrobić, należy zastąpić OnApplyTemplate. Jest to powszechna praktyka i pozwala na odłączenie twojego stylu od kontroli. (Styl nie powinien zależeć od kontrolki, ale kontrolka powinna zależeć od posiadania stylu).


7
Fobie Myślę, że celem oddzielenia Słownika od strony jest możliwość ponownego wykorzystania i czytelności strony głównej xaml. U mnie też to rozwiązanie zadziałało.
cleftheris

5

Gishu - chociaż może się to wydawać, że jest to praktyka „generalnie nie do zachęcania”. Oto jeden z powodów, dla których warto to zrobić:

Standardowym zachowaniem pól tekstowych, gdy są one aktywne, jest umieszczenie karetki w tym samym miejscu, w którym było, gdy formant stracił fokus. Jeśli wolisz, aby w całej aplikacji, gdy użytkownik przechodził do dowolnego pola tekstowego, cała zawartość pola tekstowego była podświetlona, ​​dodanie prostego modułu obsługi w słowniku zasobów załatwi sprawę.

Każdy inny powód, dla którego chcesz, aby domyślne zachowanie interakcji użytkownika różniło się od zachowania po wyjęciu z pudełka, wydaje się być dobrym kandydatem na kod znajdujący się w słowniku zasobów.

Całkowicie zgadzam się, że wszystko, co jest specyficzne dla funkcji aplikacji, nie powinno znajdować się w kodzie za słownikiem zasobów.


0

XAML służy do konstruowania grafów obiektów niezawierających kodu.
Szablon danych służy do wskazania, w jaki sposób niestandardowy obiekt użytkownika ma być renderowany na ekranie ... (np. Jeśli jest to element listy) zachowanie nie jest częścią obszaru specjalizacji szablonu danych. Przerysuj rozwiązanie ...


Wniosek: Czy poleciłbyś używanie dic zasobów z kodem, czy nie? Nigdy go nie użyłem, wątpię.
Shimmy Weitzhandler

1
Nie chciałbym - nie wydaje mi się to właściwe. Słownik powinien zwracać wartości dla określonych kluczy. W przypadku OP, łączenie kodu z szablonem danych… Wolałbym spróbować innego podejścia… na przykład użyć modelu poleceń. Potrzebuję więcej szczegółów na temat problemu OP, aby polecić rozwiązanie różnicowe.
Gishu

1
Całkowicie się nie zgadzam. W przypadku MVVM istnieje jeden scenariusz, w którym posiadanie kodu jest niezwykle przydatne: tworzenie dołączonych właściwości. Uruchom go z kodem, a następnie przenieś go do dołączonej właściwości. Jest to znacznie szybsze niż po prostu rozwijanie dołączonej właściwości od zera, chyba że masz mózg wielkości Manhattanu.
Contango
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.