2016-04-03 10 views
0

WPF MVVMを使用してListをUniformGridにWPウィンドウにバインドする必要があります。私のVM中に、ViewModelリスト(WPF MVVM)にViewコントロールを正しくバインドする方法

私はこのような何かを念頭に置いていたリストには、イベントを通じてビューにリフレッシュする必要があるとき

private List<Rat> rats; 
     private UniformGrid uniformGrid; 
     public List<Rat> Rats 
     { 
      get { return rats; } 
      set 
      { 

       if (rats != value) 
        { 
        //update local list value 
         rats = value; 

        //create View UniformGrid 
         if (uniformGrid == null) 
          uniformGrid = new UniformGrid() { Rows=10}; 
         else 
          uniformGrid.Children.Clear(); 
        foreach(Rat rat in value) 
        { 
         StackPanel stackPanel = new StackPanel(); 
         Ellipse ellipse = new Ellipse(){Height=20, Width=20, Stroke= Brushes.Black}; 
         if (rat.Sex== SexEnum.Female) 
          ellipse.Fill= Brushes.Pink; 
         else 
          ellipse.Fill= Brushes.Blue; 

         stackPanel.Children.Add(ellipse ); 
         TextBlock textBlock = new TextBlock(); 
         textBlock.Text= rat.Name + " (" + rat.Age +")"; 
         stackPanel.Children.Add(textBlock ); 
         uniformGrid.Children.Add(stackPanel); 
        } 


         OnPropertyChanged("Rats"); 
        }    
      } 
     } 

VMが正しく通知されます。 この時点で私はビューがVMに正しくバインドされている必要があります。私はそれをこのようにしました:

<GroupBox x:Name="GB_Rats" Content="{Binding Rats}" Header="Rats" HorizontalAlignment="Left" Height="194" Margin="29,10,0,0" VerticalAlignment="Top" Width="303"> 

これは正しいグローバル承認ですか?コードを実行しようとすると、この行が実行に失敗し

具体的には、:

uniformGrid = new UniformGrid() { Rows=10}; 

- >

An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationCore.dll 
Additional information: The calling thread must be STA, because many UI components require this. 

これは私が、私はMVVMポイントからこの道を進むべきではないと思いますビューの。

あなたの親切な援助のためにThx。

答えて

3

ViewModelは、UIコントロールをインスタンス化することは想定されていません。これは、ビューの責任である必要があります。

だからあなたのコードの中であなたがStackPanelsを作成しようとするべきではない、Ellipsesなど

また、既に変更通知を持っているタイプを使用しようとする - の代わりに、 List<T>使用ObservableCollection<T>MSDNのために、私はお勧めしませんその値が変更されたときにリスト全体を置き換えます。

MVVMパターンでこれを行うための正しい方法は、このようRatためDataTemplateを作成することです:

のViewModel:

public class MainWindowViewModel 
{ 
    public ObservableCollection<Rat> Rats { get; set; } = 
     new ObservableCollection<Rat>() 
     { 
      new Rat() 
      { 
       Name = "Fred", 
       Age = "19", 
       Sex = SexEnum.Male 
      }, 
      new Rat() 
      { 
       Name = "Martha", 
       Age = "21", 
       Sex = SexEnum.Female 
      } 
     }; 

} 

モデル - ラットとセックス:

public class Rat 
{ 
    public SexEnum Sex { get; set; } 
    public string Name { get; set; } 
    public string Age { get; set; } 
} 

public enum SexEnum 
{ 
    Female, 
    Male 
} 

セックスのモデル値を2色のいずれかで表示したい場合は、IValueConverterを使用してください:

[ValueConversion(typeof(SexEnum), typeof(Brush))] 
public class SexToColorConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (!(value is SexEnum)) 
      throw new ArgumentException("value not of type StateValue"); 
     SexEnum sv = (SexEnum)value; 
     //sanity checks 
     if (sv == SexEnum.Female) 
      return Brushes.Red; 
     return Brushes.Blue; 
    } 

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

これは、あなたの窓に使用されます。

ウィンドウ:

<Window x:Class="WpfApplication1.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:WpfApplication1" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525" 
     xmlns:ViewModel="WpfApplication1.VM" 
     xmlns:Converters ="clr-namespace:WpfApplication1.Converters" 
     > 
    <Grid> 
     <Grid.Resources> 
      <Converters:SexToColorConverter x:Key="SexToBrushConverter"></Converters:SexToColorConverter> 
     </Grid.Resources> 
     <ComboBox x:Name="comboBox" ItemsSource="{Binding Rats}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="120"> 
      <ComboBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal"> 
         <Ellipse Width="10" Height="10" Fill="{Binding Sex, Converter={StaticResource SexToBrushConverter}}"></Ellipse> 
         <TextBlock Margin="5" Text="{Binding Name}"></TextBlock> 
         <TextBlock Margin="5" Text="{Binding Age}"></TextBlock> 
        </StackPanel> 
       </DataTemplate> 
      </ComboBox.ItemTemplate> 
     </ComboBox> 

    </Grid> 
</Window> 

注色を変更するComboBox.ItemTemplate財産とConverters:SexToColorConverterの宣言とその使用に割り当てられているDataTemplateFillバインディング内の楕円の

更新4.4。私はあなたがのリストを追加したいようにしたいどのようにMVVM純粋主義者によっては、ターゲットはまたラットを選択することで推測リストに

<Window x:Class="WpfApplication1.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:WpfApplication1" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525" 
     xmlns:Converters ="clr-namespace:WpfApplication1.Converters" 
     xmlns:vm="clr-namespace:WpfApplication1.VM"> 
    <Window.DataContext> 
     <vm:MainWindowViewModel/> 
    </Window.DataContext> 
    <Grid> 
     <Grid.Resources> 
      <Converters:SexToColorConverter x:Key="SexToBrushConverter"></Converters:SexToColorConverter> 
     </Grid.Resources> 
     <GroupBox> 
      <ItemsControl ItemsSource="{Binding Rats}" > 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <StackPanel Orientation="Horizontal"> 
          <CheckBox Margin="5"></CheckBox> 
          <Ellipse Width="10" Height="10" Fill="{Binding Sex, Converter={StaticResource SexToBrushConverter}}"></Ellipse> 
          <TextBlock Margin="5" Text="{Binding Name}"></TextBlock> 
          <TextBlock Margin="5" Text="{Binding Age}"></TextBlock> 
         </StackPanel> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 
     </GroupBox> 
    </Grid> 
</Window> 

を表示するCheckBoxesGroupBoxを使用して2016年16:30 ウィンドウRatViewModelsは、ブールのIsCheckedプロパティを持ち、ItemsSourceObservableCollection<RatViewModel>にバインドし、このリストをモデルと同期させます。List<Rat>

+0

鮮やかな答えです。ありがとう、トン。質問を閉じる前に、ComboBoxまたはListBoxに切り替えるのではなく、Groupboxに固執する方法を知っていますか? アプリケーションのデザインを保持するためにGroupBoxを使用する必要があります。しかし、GroupBoxにはUniformGridではなくItemsSourceプロパティがありません。申し訳ありませんが –

+0

は 'GroupBox' を逃した - ' GroupBox'は、あなたが '' ComboBox'などをItemControl'にアイテムのカスタム量をバインドする必要があり、実際に結合するためのものだけでなく、コンテナです。そこで、チェックボックスを含むようにテンプレートを編集する必要があります。あなたがそこで追求している目標は何ですか?その後、選択したラットを取得する必要がありますか? –

+0

それだけで魅力をworkslike、あなたのassistance.Earnedmeためthanksaゲインに多くの時間! –

関連する問題