【问题标题】:WPF: Manipulating DataGrid binding in ViewModelWPF:在 ViewModel 中操作 DataGrid 绑定
【发布时间】:2015-05-12 06:30:38
【问题描述】:

让我们考虑以下三个类:

public class Animal
{
    public string name { set; get; }
    public string genome { set; get; }
}
public class Car
{
    public string name { set; get; }
    public int model { set; get; }
    public int horsePower { set; get; }
}
public class Tree
{
    public string name { set; get; }
    public int age { set; get; }
}

每种类型的集合如下:

    ObservableCollection<Animal> animals { set; get; }
    ObservableCollection<Car> cars { set; get; }
    ObservableCollection<Tree> trees { set; get; }

我们有一个ComboBox,它的项目是animalscarstrees。根据用户的选择,这些集合中的每一个都将显示在DataGrid 中。但是,由于数据类型不同,因此无法预先定义适当的列绑定,并且必须针对ComboBox 选择更改绑定。您对如何解决这种情况有什么建议吗?

假设:

  • 我们处于 MVVM 模式。
  • 我们不希望每种类型都有一个 DataGrid(总计最多 3 个 DataGrids)。
  • 我们不允许修改模型。

【问题讨论】:

  • 亲爱的@Hamed,正如您从后面代码中的任何绑定示例中看到的那样,您需要为 UI 元素指向 DependencyProperty,并且根据 MVVM 方法,我们将模型和视图分开,如您所知。所以你的问题的标题是"Manipulating DataGrid binding in ViewModel" 不是一个好主意。但我曾试图给你一个关于你的动态目标的想法。

标签: c# wpf mvvm binding datagrid


【解决方案1】:

如果您不想要多个数据网格,我会使用一个包含所有对象类型的所有列的单个数据网格。在运行时,您将隐藏与当前类型无关的列。 顺便说一句,这与拥有多个数据网格并隐藏与当前类型无关的数据网格没有任何不同。

【讨论】:

  • 我喜欢一个包含所有列的通用数据网格的想法。但是我仍然无法弄清楚如何拥有彼此相反的多重绑定或转换器。例如,转换animal.name 的转换器不同于修改tree.name 的转换器。在您的提议中,我还应该有不同的 name 列,它们可以工作,但不是一个干净优雅的解决方案。
  • 如果 variuos Name 列之间的唯一区别是 ValueConverter,我认为您可以在运行时使用 GetBindingExpression / SetBinding 切换它。如果还有其他差异(验证、布局等),我会选择 3 个不同的列(尽管名称相同,但它们会是不同的东西)。
【解决方案2】:

您可以为每个类创建一个DataTemplate,然后在运行时使用DataTemplateSelector 更改模板,例如this

【讨论】:

  • 这很有趣,但是您认为 DataTemplate 也可以帮助 itemSource 吗?
【解决方案3】:

如果你想动态绑定数据到DataGrid,我们可以使用dynamic类型。

如下创建一个属性

public ObservableCollection<dynamic> SampleListData
    {
        get { return _sampleListData; }
        set { _sampleListData = value; NotifyPropertyChanged("SampleListData"); }
    }

-在 XAML 中将组合框选定的值绑定到属性

<ComboBox x:Name="cbStatus" SelectedValuePath="Content" SelectedValue="{Binding selectedStatus, Mode=TwoWay}" HorizontalAlignment="Left" Height="25" Margin="67,5,0,0" VerticalAlignment="Top" Width="160" Grid.Row="1">
        <ComboBoxItem x:Name="opAnimal" Content="Animal"/>
        <ComboBoxItem x:Name="opCar" Content="Car"/>
        <ComboBoxItem x:Name="opTree" Content="Tree"/>
    </ComboBox>

-等combobox值改变,可以根据选中的值绑定itemsource。

public string selectedStatus
    {
        get { return _selectedStatus; }
        set 
        {
            _selectedStatus = value; NotifyPropertyChanged("selectedStatus");
            if (selectedStatus == "Tree")
            {
                SampleListData = new ObservableCollection<dynamic>();

                SampleListData.Add(new Tree { name = "Mohan", age = 25 });
                SampleListData.Add(new Tree { name = "Tangella", age = 28 });
            }
            if (selectedStatus == "Car")
            {
                SampleListData = new ObservableCollection<dynamic>();

                SampleListData.Add(new Car { name = "Mohan", horsePower=68,model = 1 });
                SampleListData.Add(new Car { name = "Mohan", horsePower = 72, model = 1 });
            }
            if (selectedStatus == "Animal")
            {
                SampleListData = new ObservableCollection<dynamic>();

                SampleListData.Add(new Animal { name = "Tiger", genome="H" });
                SampleListData.Add(new Animal { name = "Lion", genome="FG" });
            }
        }
    }

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2012-02-23
    • 1970-01-01
    • 2020-03-29
    • 2011-04-13
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 2015-07-02
    • 2014-05-26
    相关资源
    最近更新 更多