2016-04-23 8 views
0

Ich habe ein Beispiel erstellt basierend auf MVVM Hauptfenster XAML:aktualisieren withing von MVVM

<Window x:Class="LearnMVVM.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:LearnMVVM" 
     xmlns:System="clr-namespace:System;assembly=mscorlib" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <local:ViewModel /> 
    </Window.DataContext> 
    <Window.Resources> 
     <ObjectDataProvider x:Key="operationTypeEnum" MethodName="GetValues" ObjectType="{x:Type System:Enum}"> 
      <ObjectDataProvider.MethodParameters> 
       <x:Type TypeName="local:OperationType"/> 
      </ObjectDataProvider.MethodParameters> 
     </ObjectDataProvider> 
     <DataTemplate DataType="{x:Type local:SomeUserControlViewModel}"> 
      <local:SomeUserControl /> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition/> 
      <ColumnDefinition Width="25"/> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="25"/> 
      <RowDefinition Height="25"/> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <TextBox Grid.Column="0" Grid.Row="0" Margin="2" Text="{Binding Path=A, Mode=TwoWay}"/> 
     <TextBlock Grid.Column="1" Grid.Row="0" Text="+" TextAlignment="Center" VerticalAlignment="Center" Height="16" Margin="0,4,0,5"/> 
     <TextBox Grid.Column="2" Grid.Row="0" Margin="2" Text="{Binding Path=B, Mode=TwoWay}"/> 
     <Button Grid.Column="3" Grid.Row="0" Margin="2" Content="Посчитать" Command="{Binding ClickCommand}"/> 
     <TextBox Grid.Column="4" Grid.Row="0" Margin="2" IsReadOnly="True" Text="{Binding Path=Summa, Mode=TwoWay}"/> 

     <ComboBox Grid.Column="2" Grid.Row="1" SelectedItem="{Binding Path=SomeUserControl.Operation, Mode=TwoWay}" ItemsSource="{Binding Source={StaticResource operationTypeEnum}}" /> 
     <ContentControl Grid.Column="2" Grid.Row="2" BorderThickness="3" BorderBrush="Black" Content="{Binding Path=SomeUserControl}" /> 
    </Grid> 
</Window> 

XAML des SomeUserControl:

<UserControl x:Class="LearnMVVM.SomeUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:learnMvvm="clr-namespace:LearnMVVM" 
      xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <UserControl.DataContext> 
     <learnMvvm:SomeUserControlViewModel /> 
    </UserControl.DataContext> 
    <DockPanel> 
     <TextBox DockPanel.Dock="Top" Margin="10" Text="{Binding Path=A, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}" /> 
     <Label DockPanel.Dock="Top" Content="{Binding Path=Operation, diag:PresentationTraceSources.TraceLevel=High}" /> 
     <TextBox DockPanel.Dock="Top" Margin="10" Text="{Binding Path=B, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}" /> 
     <Button DockPanel.Dock="Top" Content="=" Margin="20" Command="{Binding CalculateOperationComamnd, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}" /> 
     <Label DockPanel.Dock="Top" Margin="10" Content="{Binding Path=Result, diag:PresentationTraceSources.TraceLevel=High}" /> 
    </DockPanel> 
</UserControl> 

Ansichtsmodell des SomeCustomUserControl:

using System; 
using System.ComponentModel; 
using System.Windows.Input; 

namespace LearnMVVM 
{ 
    public enum OperationType 
    { 
     Sum, 
     Sub, 
     Div, 
     Mul 
    } 

    public class SomeUserControlViewModel : INotifyPropertyChanged 
    { 
     public double A { get; set; } 
     public double B { get; set; } 

     //Команды 
     private ICommand calculateOperationCommand; 
     public ICommand CalculateOperationComamnd 
     { 
      get 
      { 
       return calculateOperationCommand; 
      } 
      set 
      { 
       if (calculateOperationCommand != value) 
       { 
        calculateOperationCommand = value; 
        OnPropertyChanged("CalculateOperationComamnd"); 
       } 
      } 
     } 

     private OperationType operation; 
     public OperationType Operation 
     { 
      get 
      { 
       return operation; 
      } 

      set 
      { 
       if (operation != value) 
       { 
        operation = value; 
        switch (operation) 
        { 
         case OperationType.Sum: 
          CalculateOperationComamnd = new RelayCommand(arg => OperationSum()); 
          break; 
         case OperationType.Sub: 
          CalculateOperationComamnd = new RelayCommand(arg => OperationSub()); 
          break; 
         case OperationType.Div: 
          CalculateOperationComamnd = new RelayCommand(arg => OperationDiv()); 
          break; 
         case OperationType.Mul: 
          CalculateOperationComamnd = new RelayCommand(arg => OperationMul()); 
          break; 
        } 
        OnPropertyChanged("Operation"); 
       } 
      } 
     } 

     private void OperationSum() 
     { 
      Result = A + B; 
     } 

     private void OperationSub() 
     { 
      Result = A - B; 
     } 

     private void OperationDiv() 
     { 
      Result = A/B; 
     } 

     private void OperationMul() 
     { 
      Result = A*B; 
     } 

     private double result; 
     public double Result 
     { 
      get { return result; } 
      set 
      { 
       if (Math.Abs(result - value) > 0.0001) 
       { 
        result = value; 
        OnPropertyChanged("Result"); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

    } 
} 

Problem: das benutzerdefinierte Steuerelement ändert sich nicht, wenn ich ausgewähltes Element von th Das Kombinationsfeld und die Schaltfläche "Berechnen" hat keine Wirkung.

Tatsächlich werden alle Eigenschaften in SomeCustomControlViewModel wie erwartet aktualisiert, aber es gibt keinen Effekt in den Hauptfenstern.

Habe ich etwas verpasst?

Antwort

2

Operation ist keine Eigenschaft von SomeUserControl. Es ist eine Eigenschaft von SomeUserControl 's Viewmodel - erreichbar als DataContext des Controls. Versuchen Bindung ComboBox.SelectedItem wie so:

SelectedItem="{Binding Path=SomeUserControl.DataContext.Operation, Mode=TwoWay}" 

Die Änderung ist, dass ich DataContext auf den Weg gegeben.

Aus diesem Grund verwenden Sie Viewmodels mit benutzerdefinierten Steuerelementen nicht, wenn Sie sie wirklich als Steuerelemente verwenden möchten. Sie schreiben eine Steuerelementklasse, die von Control stammt, und geben Sie Abhängigkeitseigenschaften an. Operation sollte eine Abhängigkeitseigenschaft einer Klasse sein, die von Control abgeleitet wurde, keine Benachrichtigungseigenschaft in einem Ansichtsmodell. Dann definieren Sie die Benutzeroberfläche dafür, indem Sie eine ControlTemplate über eine Standardeinstellung Style anwenden.

Was Sie hier haben, ist wirklich ein Kind Viewmodel. Bei dieser Art von Anordnung würde das Eltern-View-Modell normalerweise eine Instanz des Child-View-Modells bereitstellen und es an das Kind-Steuerelement selbst binden. Dann würde jemand, der eine Eigenschaft des Kind-Viewmodels verwenden wollte, ChildVM.WhateverProperty binden.

+0

Vielen Dank! Es gab ein weiteres Problem - SomeUserControl wurde als SomeUserControlViewModel definiert, ich habe es in SomeUserControl geändert und jetzt funktioniert es wie erwartet. – Vadim

Verwandte Themen