在WPF MVVM中的GridView中动态创建列

时间:2014-07-23 13:50:26

标签: c# wpf gridview mvvm

我的MVVM WPF应用程序当前有一个GridView,它绑定到ViewModel属性并且在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:一个“Order”对象和一个布尔值,用于控制是否为此特定视图“选中”。

但是,“选定”属性尚未建模。据了解,每个订单需要多个“选定”属性,具体取决于订单中的日期数量,可以在1到5之间。

要在UI中对此进行建模,我需要使用动态构造替换单个Checkbox GridViewColumn,该构造为订单中的每个日期创建类似的Checkbox GridviewColumn。因此GroupedOrders变为Tuple <Order, List<bool>>,而列表中的每个bool都需要有一列。

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

但是,我无法在MVVM中看到如何做到这一点。现有的解决方案似乎适用于代码隐藏,其中GridView可以作为对象抓取并在运行中进行操作。我见过的唯一一个MVVM解决方案是使用转换器来动态构建整个GridView,这对于这种情况来说似乎是一种大规模的过度杀伤,其中GridView中有很多列,但只有少数列需要充满活力。

还有其他办法吗?

1 个答案:

答案 0 :(得分: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; }
}

结果

Result