簡體   English   中英

如何將View控件正確綁定到ViewModel列表(WPF MVVM)

[英]how to correctly bind a View control to a ViewModel List (WPF MVVM)

我需要使用WPF MVVM將列表綁定到UniformGrid的WP窗口中。

我想到了做這樣的事情:

進入我的VM:

   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。 因此,在這一點上,我需要將View正確綁定到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的角度來看,我不應該這樣做。

謝謝您的協助。

ViewModel不應實例化任何UI控件,這應由View負責。

因此,在您的代碼中,您不應嘗試創建StackPanelsEllipses等。

也嘗試使用已經具有Change通知的類型-對於List<T>而不是ObservableCollection<T> MSDN ,我不建議在其值更改時替換整個列表。

在MVVM模式中執行此操作的正確方法是為Rat創建一個DataTemplate ,如下所示:

視圖模型:

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
}

當您想用兩種顏色之一顯示Sex的Models值時,應為此使用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屬性的DataTemplateConverters:SexToColorConverter的聲明及其在Fill綁定中更改橢圓顏色的用法。

更新4.4.2016 16:30使用帶有CheckBoxesGroupBox窗口以顯示列表

<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>

我想目標是也要選擇Rats,具體取決於您想要成為MVVM的純潔者的方式,您將添加一個RatViewModels列表,該列表具有bool IsChecked屬性並將ItemsSource綁定到ObservableCollection<RatViewModel>並將此列表與您的型號List<Rat>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM