2010-01-26 11 views
7

Dochodzę do punktu w aplikacji WPF, w której wszystkie powiązania na moich formantach stają się dość powtarzalne, a także zbyt szczegółowe. Również jeśli chcę zmienić to wiązanie, będę musiał zmienić je w różnych miejscach, a nie tylko w jednym.Jakikolwiek sposób na ponowne użycie powiązań w WPF?

Czy istnieje sposób na zapisanie źródłowej części wiązania, tak jak w zasobach, a następnie ponowne użycie go przez odniesienie do bardziej kompaktowej składni. Rozglądałem się za takimi możliwościami, ale tego nie znalazłem.

Co robię teraz

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <Grid Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <TextBox Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <CheckBox Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
</StackPanel> 

Co chcę móc wykonać (Pseudokod)

<StackPanel> 
    <StackPanel.Resources> 
     <Variable x:Name="someToggleButtonIsChecked" 
        Type="{x:Type Visibility}" 
        Value="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    </StackPanel.Resources> 

    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <Grid Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <TextBox Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <CheckBox Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
</StackPanel> 

Czy istnieje jakikolwiek inny podobny rodzaj podobną funkcję lub techniki, które pozwoli mi zadeklarować wiążące źródło raz, a następnie ponownie użyć?

+0

Generowanie kodu ??? –

Odpowiedz

1

Możesz po prostu związać właściwość z właściwością swojego modelu wyświetlania (DataContext) i użyć tej właściwości. Byłoby to wyglądać mniej więcej tak:

<StackPanel> 
<ToggleButton x:Name="someToggleButton" IsChecked="{Binding ToggleVisibility, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}}" /> 
<Button Visibility="{Binding ToggleVisibility}" /> 
<Grid Visibility="{Binding ToggleVisibility}" /> 
<TextBox Visibility="{Binding ToggleVisibility}" /> 
<CheckBox Visibility="{Binding ToggleVisibility}" /> 
</StackPanel> 

Wymagałoby to, że Window „s DataContext ma właściwość o nazwie ToggleVisibility typu Visibility.

EDIT:

Aby eleborate dalej, Twój ViewModel mógłby wyglądać następująco:

public class SomeViewModel : INotifyPropertyChanged 
{ 

    private Visibility toggleVisibility; 

    public SomeViewModel() 
    { 
     this.toggleVisibility = Visibility.Visible; 
    } 

    public Visibility ToggleVisibility 
    { 
     get 
     { 
      return this.toggleVisibility; 
     } 
     set 
     { 
      this.toggleVisibility = value; 
      RaisePropertyChanged("ToggleVisibility"); 
     } 
    } 

    private void RaisePropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 
} 

I czy wtedy ustawić instancję nim jako DataContext na Window lub nawet tylko na StackPanel

+0

To jest rzeczywiście podobne do tego, co miałem pierwotnie, ale było całkiem sporo kodu do dodania do mojego kodu dla tylko jednej właściwości. W dłuższej perspektywie, jeśli nie ma rozwiązań opartych na XAML, prawdopodobnie powrócę do robienia tego trochę bardziej podobnego do MVVM. – jpierson

+0

@Jpierson Naprawdę powinieneś wrócić do korzystania z MVVM. Mam na myśli, że masz już pole tekstowe, którego wartość można powiązać z viewmodel, i przycisk, którego polecenie można również powiązać z viewmodel. Moim zdaniem, viewmodels to właściwa droga, podczas gdy kod w twoich oknach nie jest. –

+0

Używam ViewModels obecnie w moim głównym kodzie, ale ten kod jest w małym oknie dialogowym i dodanie ViewModel zbyt wydawało się zbędne, ponieważ tak naprawdę nie było "Model", aby z powrotem mój ViewModel. Inną kwestią, którą mam w tym samym czasie, jest przypadek, w którym muszę połączyć BoolToVisibilityConverter i InverseBoolConverter w wiązanie kontrolki. Przez utworzenie właściwości w moim kodzie za lub w ViewModel szczególnie o nazwie IsNotDeleteMode będzie działać, ale wtedy mam proroctwa IsAddMode, IsNotAddMode, IsDeleteMode i IsNotDeleteMode. Wygląda mi na bałagan, niezależnie od tego, dokąd zmierza. – jpierson

0

Czy istnieje sposób na zapisanie części źródłowej powiązania po takim, jak w source, a następnie użyj go ponownie, odwołując się do bardziej zwartej składni.

Być może możesz to zrobić za pomocą PyBinding. Nie znam zasięgu jego możliwości, ale używam go przez cały czas dla unikalnych konwerterów. Oto przykład, którego często używam.

Visibility="{p:PyBinding BooleanToVisibility(IsNotNull($[.InstanceName]))}" 
  • BooleanToVisibility jest funkcją pisałem w IronPython.
  • $ [. InstanceName] wiąże się z właściwością InstanceName bieżącego elementu związanego z danymi.

EDYCJA: Można również użyć tego do powiązania właściwości jednego interfejsu użytkownika z cudzymi. Oto kilka informacji z pliku pomocy.

  • $ [NameTextBlock.Tekst] - Właściwość tekstowa elementu z x: Nazwa równa "NameTextBlock"
  • $ [NameTextBlock] - Rzeczywista instancja TextBlock, a nie jedna z jej właściwości
  • $ [{Self}] - Powiąż ze swoim samego siebie. Odpowiednik {Binding RelativeSource = {RelativeSource Self}}
  • $ [{Self} .Text] - Własność Text z własnego. Odpowiednik {Binding Path = Tekst, RelativeSource = {RelativeSource self}}

http://pybinding.codeplex.com/

Nietestowane Teoria

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}" /> 
    <Grid Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
    <TextBox Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
    <CheckBox Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
</StackPanel> 

Druga próba

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Name="myButton" Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}" /> 
    <Grid Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
    <TextBox Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
    <CheckBox Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
</StackPanel> 
+0

To było całkiem schludne i coś, czego nie wiedziałem. Problem polega na tym, że faktycznie chcę przechowywać wiązanie w jednym miejscu. Powiedz na przykład, że w pewnym momencie chcę zmodyfikować widoczność wszystkich tych kontrolek, które mają być wyłączone z właściwości ToggleButton.IsEnabled. Musiałbym zmienić to wiele miejsc i dlatego jestem zainteresowany deklarowaniem go raz, a następnie ponownym użyciem. – jpierson

+0

Możesz nazwać swój przycisk, a następnie powiązać widoczność wszystkich pozostałych elementów sterujących. Wiem, że nie jest to dokładnie to, czego chcesz, ale jest bliżej. –

+0

Tak, też to zrobiłem. Zabierając go na inny poziom, mogłem stworzyć ogólny kontrolek niestandardowy z jedną właściwością o nazwie podobnej do Value (MyBindingControl ). Następnie dla każdego typu, który chcę ponownie użyć, wiązanie dla I może utworzyć wyspecjalizowaną klasę, taką jak StringBindingControl: MyBindingControl . To może być następnie użyte jako rodzaj zmiennej, do której mogą się przyłączyć inne kontrolki. Głównym problemem związanym z tą techniką jest to, że trudno jest jej ponownie użyć w standardowych stylach/szablonach w słownikach zasobów, ponieważ najprawdopodobniej będzie polegać na nazwanych kontrolkach. – jpierson

0

Po prostu patrząc na oryginalnym kodzie , możesz pogrupować niezbędne elementy w swoim własnym kontenerze, a następnie zarządzać kontenerem Visibilit y:

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <StackPanel Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}"> 
     <Button /> 
     <Grid /> 
     <TextBox /> 
     <CheckBox /> 
    </StackPanel> 
</StackPanel> 

Faktycznie, dziś byłoby to zrobić z VSM - mają państwa z elementów widocznych i państwa z nich nie jest widoczny, a następnie użyć dwóch GoToState zachowań na przycisk Przełącz do ustawiania stanu w oparciu o przycisk przełączania stanu.

+1

Dobrze, jednak ten kod został właśnie stworzony, aby wykazać chęć ponownego wykorzystania wiązań w ogóle. Można dostrzec przypadki, w których elementy, które są związane, nie są równo rozmieszczone jako elementy równorzędne w jednym pojemniku. – jpierson