【问题标题】:Create columns dynamically in a GridView in WPF MVVM在 WPF MVVM 的 GridView 中动态创建列
【发布时间】:2014-09-14 17:52:59
【问题描述】:

我的 MVVM WPF 应用程序当前有一个绑定到 ViewModel 属性的 GridView 并具有在 XAML 中定义的列:

<ListView Grid.Row="0" ItemsSource="{Binding GroupedOrders}">
    <ListView.View>
            <GridView>
                <GridViewColumn>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding Item2, Mode=OneWay}" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Date" DisplayMemberBinding="{Binding Item1.Date, StringFormat={}{0:dd/MM/yyyy}}" />
                <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Item1.Name}" />
                <!-- lots more -->
            </GridView>
    </ListView.View>
</ListView>

GroupedOrders 是一个包含两种不同项目类型的元组的 ObservableCollection:一个“订单”对象和一个布尔值,用于控制对于此特定视图是否“被选中”。

但是,该“选定”属性的建模并不好。据了解,每个订单都需要多个“选定”属性,具体取决于订单中的日期数,可能介于 1 到 5 个之间。

要在 UI 中对此进行建模,我需要将单个 Checkbox GridViewColumn 替换为一个动态构造,该构造为订单中的每个日期创建一个类似的 Checkbox GridviewColumn。所以 GroupedOrders 变成了Tuple &lt;Order, List&lt;bool&gt;&gt;,并且列表中的每个布尔值都需要一列。

在任何给定的情况下,该列表的大小对于网格中的所有订单都是相同的。但是如果用户将新数据加载到网格中,列表的大小会发生变化。

但是,我看不到如何在 MVVM 中执行此操作。现有的解决方案似乎是用于代码隐藏,其中 GridView 可以作为对象被抓取并动态操作。我见过的唯一 MVVM 解决方案是使用转换器即时构建整个 GridView,这对于这种情况来说似乎是巨大的矫枉过正,因为 GridView 中有很多列但只有少数列需要动态。

还有其他方法吗?

【问题讨论】:

  • 您能否进一步解释一下multiple "selected" properties?它是Dictionary&lt;string, bool&gt; 的一种吗?每一行都有相同的“多个选定属性”计数?
  • @YuliamChandra 谢谢!它目前是一个 Tuple 但效果大致相同。它需要成为一个 Tuple> 以便可以独立选择每个日期。对于给定的实例,每一行将具有相同数量的日期,但如果用户将一些新数据加载到数据网格中,它可能会发生变化。我已经编辑了这个问题以反映这一点。有意义吗?
  • 嗯.. 如果States 是订单中的集合,那么列是绑定到州的ListView 怎么样? State是一个包含Name(string)和Value(bool)属性的类吗?
  • @YuliamChandra 所以...您可以通过将整个 ListView 放在单个列中来创建动态列?我不知道这是可能的!如果我能让它正常工作,那么是的,你所提议的似乎是一个很好的解决方案。
  • 是的 ListView 在 GridViewColumn 内,然后只需隐藏内部 ListvView 标题并将其方向设置为 Horizontal。

标签: c# wpf gridview mvvm


【解决方案1】:

不确定这是你所期望的,但这是我能想到的。

查看

<ListView ItemsSource="{Binding Orders}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="State">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <ListView ItemsSource="{Binding States}">
                            <ListView.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal"></StackPanel>
                                </ItemsPanelTemplate>
                            </ListView.ItemsPanel>
                            <ListView.Resources>
                                <Style TargetType="GridViewColumnHeader">
                                    <Setter Property="Visibility" Value="Collapsed" />
                                </Style>
                            </ListView.Resources>
                            <ListView.View>
                                <GridView>
                                    <GridViewColumn>
                                        <GridViewColumn.CellTemplate>
                                            <DataTemplate>
                                                <CheckBox IsChecked="{Binding Value}" Content="{Binding Text}" />
                                            </DataTemplate>
                                        </GridViewColumn.CellTemplate>
                                    </GridViewColumn>
                                </GridView>
                            </ListView.View>
                        </ListView>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="OrderNo" DisplayMemberBinding="{Binding OrderNo}" />
        </GridView>
    </ListView.View>
</ListView>

代码隐藏

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Orders.Add(new Order { OrderNo = "Order001" });
        Orders.Add(new Order { OrderNo = "Order002" });
        Orders.Add(new Order { OrderNo = "Order003" });
    }
    private readonly ObservableCollection<Order> _orders = new ObservableCollection<Order>();
    public ObservableCollection<Order> Orders
    {
        get { return _orders; }
    }
}
public class Order
{
    public Order()
    {
        States.Add(new State { Text = "Is Paid", Value = false });
        States.Add(new State { Text = "Is Delivered", Value = false });
    }
    public string OrderNo { get; set; }
    private readonly ObservableCollection<State> _states = new ObservableCollection<State>();
    public ObservableCollection<State> States
    {
        get { return _states; }
    }
}
public class State
{
    public string Text { get; set; }
    public bool Value { get; set; }
}

结果

【讨论】:

    猜你喜欢
    • 2011-07-13
    • 1970-01-01
    • 2017-09-18
    • 2021-10-06
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多