2017-10-23 7 views
1

MVVMの原則を使用してアプリケーションを学習し、作成しようとしています。何イムが作業することで、この、IValueConverterは、Comboboxの選択が変更されたときにDatagridを更新しません。

enter image description here

2 IValueConverters、それらの一方のみがトリガされすなわちは一つだけがロードされ、作品を実装しようと、データグリッドが初期化されるときにロードされるOnStockIconConverter、。

ComboBoxトグルに依存するもう1つのCurrencyConverterは、選択した値を変更するとDataGridで反応しません。

私はこれを数時間にわたって解決しようとしてきましたが、そこのコンテンツのほとんどは、MVVMの初心者にとってはあいまいです。

他のすべての質問は、私がしたいことの反対を説明します。

C#

namespace Coding_Dojo_3 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    /// 
    /// 


    public partial class MainWindow : Window 
    { 

     public ObservableCollection<StockEntryModel> StockEntriesCollection { get; } 

     public MainWindow() 
     { 

      InitializeComponent(); 
      var sampleManager = new SampleManager(); 
      StockEntriesCollection = new ObservableCollection<StockEntryModel>(); 
      foreach (var stockEntry in sampleManager.CurrentStock.OnStock) 
      { 
       StockEntriesCollection.Add((new StockEntryModel{SoftwarePackage = stockEntry.SoftwarePackage, Amount = stockEntry.Amount})); 
      } 
      DataContext = this; 
     } 

     private void ComboBoxCurrency_SelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string; 
      SelectedCurrency.Name = text; 
      Console.WriteLine("Currency changed to {0}", text); 
     } 
    } 


    public class StockEntryModel : INotifyPropertyChanged 
    { 
     private object _softwarePackage; 
     private int _amount; 

     public event PropertyChangedEventHandler PropertyChanged; 

     public object SoftwarePackage 
     { 
      get => _softwarePackage; 
      set 
      { 
       _softwarePackage = value; 
       OnPropertyChanged(nameof(SoftwarePackage)); 
      } 
     } 

     public int Amount 
     { 
      get { return _amount; } 
      set 
      { 
       _amount = value; 

       OnPropertyChanged(nameof(Amount)); 
      } 
     } 

     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 

    } 


    public class StockEntryViewModel 
    { 
     public StockEntryModel NewStockEntryModel { get; set; } 

     public StockEntryViewModel() 
     { 
      NewStockEntryModel = new StockEntryModel(); 
     } 
    } 


    public static class SelectedCurrency 
    { 
     public static String Name; 
    } 

    public class CurrencyConverter : IValueConverter 
    { 

     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      var currency = SelectedCurrency.Name; 
      switch (currency) 
      { 

       case "EUR": 
        return CodingDojo4DataLib.Converter.CurrencyConverter.ConvertFromEuroTo(Currencies.EUR, 
          (double)value); 
       case "USD": 
        return CodingDojo4DataLib.Converter.CurrencyConverter.ConvertFromEuroTo(Currencies.EUR, 
         (double)value); 
       case "GBP": 
        return CodingDojo4DataLib.Converter.CurrencyConverter.ConvertFromEuroTo(Currencies.EUR, 
         (double)value); 
       default: 
        return CodingDojo4DataLib.Converter.CurrencyConverter.ConvertFromEuroTo(Currencies.EUR, 
         (double)value); 
      } 

     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    public class OnStockIconConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      if (value is int) 
      { 
       if ((int)value < 10) 
        return "red"; 
       if ((int)value > 10 && (int)value < 20) 
        return "orange"; 
       if ((int)value > 20) 
        return "green"; 
      } 
      return "red"; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

XAML

<Window x:Class="Coding_Dojo_3.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:Coding_Dojo_3" 
     mc:Ignorable="d" 
     Title="Coding Dojo 3" Height="400" Width="1024"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="1*" /> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="0.125*" /> 
      <RowDefinition Height="1*" /> 
      <RowDefinition Height="0.125*" /> 
     </Grid.RowDefinitions> 
     <StackPanel Grid.Row="0" Orientation="Horizontal"> 
      <Label VerticalAlignment="Top">Currency :</Label> 
      <ComboBox AllowDrop="True" Name="ComboBoxCurrency" VerticalAlignment="Top" SelectionChanged="ComboBoxCurrency_SelectionChanged"> 
       <ComboBoxItem IsSelected="True">EUR</ComboBoxItem> 
       <ComboBoxItem>USD</ComboBoxItem> 
      </ComboBox> 
     </StackPanel> 
     <DataGrid Grid.Row="1" 
        Name="DataGridStock" 
        AutoGenerateColumns="False" 
        ColumnWidth="*" 
        x:FieldModifier="public" 
        IsReadOnly="False" 
        CanUserAddRows="True" 
        CanUserDeleteRows="True" 
        ItemsSource="{Binding StockEntriesCollection}"> 
      <DataGrid.Resources> 
       <local:CurrencyConverter x:Key="CurrencyConverter"/> 
       <local:OnStockIconConverter x:Key="OnStockIconConverter"/> 
      </DataGrid.Resources> 
      <DataGrid.Columns> 
       <DataGridTextColumn Header="Name" Binding="{Binding SoftwarePackage.Name}"></DataGridTextColumn> 
       <DataGridTextColumn Header="Group" Binding="{Binding SoftwarePackage.Category.Name}"></DataGridTextColumn> 
       <DataGridTextColumn Header="Sales Price" Binding="{Binding SoftwarePackage.SalesPrice, NotifyOnTargetUpdated=True, Converter={StaticResource CurrencyConverter}}"></DataGridTextColumn> 
       <DataGridTextColumn Header="Purchase Price" Binding="{Binding SoftwarePackage.PurchasePrice, NotifyOnTargetUpdated=True, Converter={StaticResource CurrencyConverter}}"></DataGridTextColumn> 
       <DataGridTextColumn Header="Amount" Binding="{Binding Amount}"></DataGridTextColumn> 
       <DataGridTextColumn Header="On Stock" Binding="{Binding Amount, Converter={StaticResource OnStockIconConverter}}"></DataGridTextColumn> 
      </DataGrid.Columns> 
     </DataGrid> 
     <StackPanel Grid.Row="2" Orientation="Horizontal"> 
      <Button Margin="3">Add</Button> 
      <Button Margin="3">Edit</Button> 
      <Button Margin="3">Delete</Button> 
     </StackPanel> 
    </Grid> 
</Window> 
+0

あなたのコンバータは静的リソースなので、 'var currency = SelectedCurrency.Name; 'という行は各呼び出しで再評価されません。 'ConverterParameter'をバインドすることはできません。代わりに' IMultiValueConverter'を使って 'MultiBinding'を使ってみてください 。 [here](https://stackoverflow.com/questions/15309008/binding-converterparameter/15309844#15309844)で説明されています。 – Funk

+0

静的クラス 'SelectedCurrency'の目的は何ですか?ステートフルな静的読み書きフィールドを含む静的クラスは、悪い設計とみなされることに注意してください。 – dymanoid

+0

@Funk病気に頭をかぶる – silberbaum

答えて

1

あなたは本当のMVVMで動作することができますのためにあなたは、あなたのviewmodelとビューを分離する必要があります。今あなたのビューは同時にビューモデルです。
目標を達成するには、入力モデルにメソッドを追加します。 NotifyAllChangedを使用してすべてのプロパティを再計算し、コンボボックスイベントハンドラで呼び出します。

public class StockEntryModel : INotifyPropertyChanged 
{ 
    ... 

    public void NotifyAllChanged() 
    { 
     OnPropertyChanged(string.Empty); 
    } 
} 

     private void ComboBoxCurrency_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string; 
     SelectedCurrency.Name = text; 
     Console.WriteLine("Currency changed to {0}", text); 

     StockEntriesCollection?.ForEach(entry=>entry.NotifyAllChanged()); // <== 
    } 
関連する問題