【问题标题】:WPF DataGrid column with variable number of buttons/shapes具有可变数量的按钮/形状的 WPF DataGrid 列
【发布时间】:2013-07-28 22:28:52
【问题描述】:

我有一个要求,在一个 DataGrid 列上,我需要并排显示 x 个可点击按钮(水平堆叠)。要显示的实际数字或按钮取决于该列中的绑定值。

下图显示了这一点。左边的网格是我现在的网格,右边的网格是我要找的。​​p>

Grid 绑定到 ViewModel 如下:

<DataGrid ItemsSource="{Binding employees}" AutoGenerateColumns="False"  >
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=id}" Header="Id" />
            <DataGridTextColumn Binding="{Binding Path=numberofplatforms}" Header="No" Width="50" IsReadOnly="True" />
        </DataGrid.Columns>
    </DataGrid>

ViewModel 是:

Public Class ViewModel

    Public Property employees As ObservableCollection(Of employee)
        Get
            Return _employees
        End Get
        Set(ByVal value As ObservableCollection(Of employee))
            _employees = value
        End Set
    End Property
    Private _employees As New ObservableCollection(Of employee)

End Class

雇员是:

Public Class employee
    Public Property id As String
    Public Property numberofplatforms As Integer
    Public Property selectedplatform As Integer
End Class

除了显示按钮之外,按钮本身必须像单选按钮一样,即在任何 DataGrid 行上,只有一个按钮被“按下”(图像中的蓝色背景按钮),其他按钮不被按下(灰色背景)。按钮(或形状)必须是可点击的,以便更改选择。

根据 selectedplatform 属性,哪个按钮被“按下”由 ViewModel 确定。此示例中的该属性对于 ABC 是 1,对于 DEF 是 1,对于 GHI 是 2。如果 numberofplatforms 属性为零,则不显示任何按钮 (JKL)。

我该如何设置这个机制?

【问题讨论】:

    标签: wpf data-binding mvvm datagrid


    【解决方案1】:

    部分代码是C#,希望没有问题。 wpf代码:

    <Window.Resources>
        <ResourceDictionary>
            <local:PositiveIntegersConverter x:Key="PositiveIntegersConverter" />
            <local:EmployeePlatformOptionConverter x:Key="EmployeePlatformOptionConverter"/>
        </ResourceDictionary>
    </Window.Resources>
    
    <DataGrid ItemsSource="{Binding employees}" AutoGenerateColumns="False" x:Name="DataGrid1">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=id}" Header="Id" />
            <DataGridTemplateColumn Header="No" IsReadOnly="True">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                            <ListBox ItemsSource="{Binding numberofplatforms, Converter={StaticResource PositiveIntegersConverter}}" SelectedItem="{Binding selectedplatform}"
                                        x:Name="ListBox1">
                                <ListBox.ItemTemplate>
                                    <DataTemplate>
                                        <Button Content="{Binding}" Command="{Binding Source={x:Reference DataGrid1}, Path=DataContext.SelectOptionCommand}">
                                            <Button.CommandParameter>
                                                <MultiBinding Converter="{StaticResource EmployeePlatformOptionConverter}">
                                                    <Binding ElementName="ListBox1" Path="DataContext"/>
                                                    <Binding Path="."/>
                                                </MultiBinding>
                                            </Button.CommandParameter>
                                            <Button.Style>
                                                <Style TargetType="Button">
                                                    <Setter Property="Background" Value="Gray" />
                                                    <Setter Property="Foreground" Value="White" />
                                                    <Style.Triggers>
                                                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}"
                                                                        Value="True">
                                                            <Setter Property="Background" Value="Blue" />
                                                        </DataTrigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </Button.Style>
                                        </Button>
                                    </DataTemplate>
                                </ListBox.ItemTemplate>
                                <ListBox.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <StackPanel Orientation="Horizontal" />
                                    </ItemsPanelTemplate>
                                </ListBox.ItemsPanel>
                            </ListBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    

    我在这里使用了两个转换器:

    PositiveIntegersConverter 返回给定 numberofplatforms 的正整数 - 这些是员工可用的平台选项

    EmployeePlatformOptionConverter 它将我们要传递给 SelectOptionCommand 的两个参数:员工和选定的平台选项转换为一个 EmployeePlatformOption 类型的对象。

    public class PositiveIntegersConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var toInteger = System.Convert.ToInt32(value);
            return toInteger > 0 ? Enumerable.Range(1, toInteger) : null;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    
    public class EmployeePlatformOptionConverter
        : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return new EmployeePlatformOption
                {
                    Employee = values[0] as Employee,
                    Platform = (int)values[1]
                };
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    使用封装对象:

    public class EmployeePlatformOption
    {
        public Employee Employee { get; set; }
        public int Platform { get; set; }
    }
    

    您将选择传递给 ViewModel 类中的 SelectOptionCommand:

    public ICommand SelectOptionCommand { get; set; }
    private void SelectOptionExecute(EmployeePlatformOption employeePlatformOption)
    {
        if (employeePlatformOption != null && employeePlatformOption.Employee != null &&
            employeePlatformOption.Platform > 0)
        {
            employeePlatformOption.Employee.selectedplatform = employeePlatformOption.Platform;
        }
    }
    

    员工应该实现 INotifyPropertyChange 接口,以便 selectedplatform 更新在屏幕上可见。

    【讨论】:

      猜你喜欢
      • 2011-10-09
      • 1970-01-01
      • 2019-07-23
      • 1970-01-01
      • 2013-01-23
      • 2015-11-07
      • 1970-01-01
      • 2011-06-06
      相关资源
      最近更新 更多