2017-08-28 1 views
-1

In WPF habe ich versucht herauszufinden, wie man eine Ansichtsabhängigkeitseigenschaft und eine der Eigenschaften des Ansichtsmodells für eine Weile ohne Erfolg halten kann. Ich habe viel über das Thema recherchiert, aber keine der vorgeschlagenen Lösungen funktioniert für mich, und ich hoffte, dass jemand mir helfen könnte, das zu finden, was mir fehlt.WPF - Wie wird die Abhängigkeitseigenschaft beibehalten und die Modelleigenschaft synchron angezeigt?

Ich habe viele der in diesem Post vorgeschlagenen Dinge versucht, Twoway-bind view's DependencyProperty to viewmodel's property?, wegen all der Dinge, die ich gelesen habe, sah es am vielversprechendsten aus, war aber nie in der Lage, die Ergebnisse zu bekommen, die ich suchte.

Ich habe ein einfaches Programm geschrieben, um dieses Problem zu demonstrieren. Darin setze ich die Eigenschaft IntValue in MainWindowViewModel auf 2 und verbinde es dann mit einer Abhängigkeitseigenschaft, die in UserControl IncrementIntView erstellt wurde. Wenn ich dann den Knopf in IncrementIntView drücke, erhöht sich der Wert von IntValue um eins. Das funktioniert alles in Ordnung innerhalb des Usercontrol IncrementIntView aber ich kann nicht herausfinden, wie die aktualisierte intValue zu MainWindowViewModel zurück zu schicken, es bleibt auf 2 gesetzt

IncrementIntView.xaml.cs

public partial class IncrementIntView : UserControl 
{ 
    public int IntValue 
    { 
     get { return (int)GetValue(IntValueProperty); } 
     set { SetValue(IntValueProperty, value); } 
    } 

    public static readonly DependencyProperty IntValueProperty = 
     DependencyProperty.Register("IntValue", typeof(int), typeof(IncrementIntView), 
             new PropertyMetadata(-1, new PropertyChangedCallback(IntValueChanged))); 

    private static void IntValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
    { 
     IncrementIntView detailGroup = dependencyObject as IncrementIntView; 
     if (e.NewValue != null) 
     { 
      detailGroup.ViewModel.IntValue = (int)e.NewValue; 
     } 
    } 

    public IncrementIntView() 
    { 
     InitializeComponent(); 
    } 
} 

IncrementIntViewModel.cs

public class IncrementIntViewModel : ViewModelBase 
{ 
    private int intValue; 
    public int IntValue 
    { 
     get { return intValue; } 
     set { SetProperty(ref intValue, value); } 
    } 

    public IncrementIntViewModel() 
    { 
     incrementIntCommand = new Command(IncrementInt); 
    } 

    private Command incrementIntCommand; 
    public Command IncrementIntCommand { get { return incrementIntCommand; } } 
    public void IncrementInt() 
    { 
     IntValue++; 
    } 
} 

IncrementIntView.xaml

<UserControl.DataContext> 
    <local:IncrementIntViewModel x:Name="ViewModel" /> 
</UserControl.DataContext> 

<Grid> 
    <StackPanel Orientation="Horizontal"> 
     <Label Content="{Binding IntValue}" /> 
     <Button Content="Increment" Command="{Binding IncrementIntCommand}" Width="75" /> 
    </StackPanel> 
</Grid> 

MainWindow.xaml.cs

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 
} 

MainWindowViewModel.cs

public class MainWindowViewModel : ViewModelBase 
{ 
    private int intValue = 2; 
    public int IntValue 
    { 
     get { return intValue; } 
     set { SetProperty(ref intValue, value); } 
    } 
} 

MainWindow.xaml

<Window.DataContext> 
    <local:MainWindowViewModel x:Name="ViewModel"/> 
</Window.DataContext> 

<Grid> 
    <StackPanel Margin="10"> 
     <local:IncrementIntView IntValue="{Binding IntValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ElementName=ViewModel}" /> 
     <Label Content="{Binding IntValue}" /> 
    </StackPanel> 
</Grid> 
+0

Beachten Sie, dass 'ElementName = ViewModel' vollständig redundant ist. Da die MainWindowViewModel-Instanz dem DataContext des Fensters bereits zugewiesen ist, müssen Sie die Binding-Quelle nicht explizit angeben. Die Binding sollte nur 'IntValue =" {Binding IntValue, Mode = TwoWay} "sein, weil' UpdateSourceTrigger = PropertyChanged' ebenfalls der Standardwert ist. – Clemens

Antwort

0

Ich kann sehen, dass Ihr Code die intValue von MainWindowViewModel der Unterkunft bis IncrementIntView der Abhängigkeitseigenschaft ist vorbei IncrementIntViewModels Eigenschaft.

Die Inkrementschaltfläche aktualisiert die IntValue-Eigenschaft des IncrementIntViewModel. Leider wird das, was in IncrementIntViewModel passiert, nicht in die IntValue-Abhängigkeitseigenschaft von IncrementIntView zurückgespiegelt. Der TwoWay-Modus befindet sich nicht zwischen der IncrementIntView-Abhängigkeitseigenschaft und der IncrementIntViewModel-Eigenschaft, sondern zwischen der Eigenschaft "MainWindowViewModel" und der Abhängigkeitseigenschaft "IncrementIntView".

Die einfache Lösung: Binden Sie das MainWindow-Label an die IntValue-Eigenschaft von IncrementIntViewModel, ohne die View-Eigenschaft zu stören.

<local:IncrementIntView x:Name="iiv" IntValue="{Binding IntValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ElementName=ViewModel}" /> 
<Label Content="{Binding DataContext.IntValue, ElementName=iiv}" /> 
<!--You need to specify DataContext.IntValue, because you have same name for both view's dependency property and viewmodel's property--> 

Hier können Sie sehen, dass MainWindowViewModel der intValue nicht so wichtig ist, weil es nur den Wert geht einmal IncrementIntViewModel und nie aktualisiert, um den Wert zu haben.

Die andere Lösung: Sie müssen Wertänderung zurück zu MainViewModel Eigenschaft auslösen.

Zunächst einmal gibt es keine Verbindung zwischen MainViewModel und IncrementIntViewModel.Eine Lösung besteht darin, das MainViewModel als Singleton zu definieren, so dass beim Aktualisieren von IncrementIntViewModel auch die Eigenschaft des MainViewModels aktualisiert werden soll.

In MainViewModel.cs

public static MainWindowViewModel SingletonInstance { get; set; } 
public MainWindowViewModel() 
{ 
    if (SingletonInstance == null) 
    { 
     SingletonInstance = this; 
    } 
} 

In IncrementIntViewModel.cs

public void IncrementInt() 
{ 
    IntValue++; 
    MainWindowViewModel.SingletonInstance.IntValue = IntValue; 
} 

Die andere andere Lösung: Ähnlich wie bei der obigen Lösung, aber wir brauchen nicht Singleton zu machen Instanz MainWindowViewModel, weil MainWindow zu Beginn mit Singleton ist.

In IncrementIntViewModel.cs

public void IncrementInt() 
{ 
    IntValue++; 
    ((MainWindowViewModel)App.Current.MainWindow.DataContext).IntValue = IntValue; 
} 

Wenn Ihre Absicht ist es, die intValue von IncrementViewModel der Unterkunft bis IncrementView der Abhängigkeitseigenschaft zu aktualisieren, dann könnten Sie fragen, warum Sie dies tun müssen, weil MVVM soll zwischen V trennen und VM. V sollte auf VM schauen, aber nicht umgekehrt.

+0

Ihre anderen und andere andere Lösungen funktionieren beide, aber wie Sie sagen, das ist nicht gültig für MVVM. Ich werde einen Schritt zurück machen und meinen Ansatz neu bewerten. Danke für die Hilfe. – ThatBaldGuy13

Verwandte Themen