DataGrid绑定行和只是一些列?

时间:2017-04-28 20:14:45

标签: xaml templates binding datagrid

enter image description here

如何使用行和模板以及可重复单元格获取这样的数据网格?

DataGrid绑定到一个名为Blocks的属性,这是一个Block类型的BindingList,在视图模型中定义:

                        <DataGrid x:Name="dgBlocks" DockPanel.Dock="Left"
                              Margin="20,10,10,20" AutoGenerateColumns="False"
                              ItemsSource="{Binding Blocks, Mode=TwoWay}" 
                              IsSynchronizedWithCurrentItem="True"
                              CanUserAddRows="False"
                              SelectionUnit="Cell" SelectionMode="Single"
                              EnableColumnVirtualization="False"
                              EnableRowVirtualization="False"
                              SelectedIndex="-1" MinRowHeight="10"                            
                              LoadingRow="dg_LoadingRow" 
                              SelectionChanged="dgBlocks_SelectionChanged"
                              >

                            <DataGrid.Resources>
                                <helper:BindingProxy x:Key="proxy" Data="{Binding}" />

                                <!--todo: change to symbol’s ‘ReadOnly’ property instead of block’s ‘Permission’ -->

                                <Style x:Key="CellPermissionStyle" TargetType="DataGridCell">
                                    <Setter Property="Background" Value="{Binding Permission, Converter={StaticResource BlockPermissionToBrushConverter}}" />
                                    <Setter Property="IsEnabled" Value="{Binding Permission, Converter={StaticResource BlockPermissionToBoolConverter}}" />
                                </Style>


                            </DataGrid.Resources>
                            <DataGrid.RowHeaderTemplate>
                                <DataTemplate>
                                    <TextBlock Name="txtBlockRowHeader"
                                               Text="{Binding Path=Header,
                                               RelativeSource={RelativeSource AncestorType=DataGridRow}}">
                                    </TextBlock>
                                </DataTemplate>
                            </DataGrid.RowHeaderTemplate>
                            <DataGrid.Columns>
                                <DataGridTemplateColumn>
                                    <!-- Selection checkboxes -->
                                    <DataGridTemplateColumn.Header>
                                        <StackPanel>
                                            <CheckBox HorizontalAlignment="Center" IsThreeState="True" ToolTip="Select All" Margin="10,0,0,0">
                                                <CheckBox.IsChecked>
                                                    <Binding Path="DataContext.SelectAll" 
                                                             RelativeSource="{RelativeSource AncestorType={x:Type UserControl}}"
                                                             Mode="TwoWay"
                                                             UpdateSourceTrigger="PropertyChanged"
                                                             />
                                                </CheckBox.IsChecked>
                                            </CheckBox>
                                        </StackPanel>
                                    </DataGridTemplateColumn.Header>
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <CheckBox Margin="5,0,0,0" IsChecked="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>

                                <DataGridTemplateColumn Width="50">
                                    <DataGridTemplateColumn.Header>
                                        <TextBlock Text="Repeat" HorizontalAlignment="Center" />
                                    </DataGridTemplateColumn.Header>
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <telerik:RadNumericUpDown Name="nudRepeatBlock" ValueFormat="Numeric" Width="40"
                                                      ToolTip="Repeat block number of times" IsInteger="True" IsEditable="True"
                                                      Minimum="1" Maximum="100" UpdateValueEvent="PropertyChanged"
                                                      Value="{Binding Repeat, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="40" />
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                                <DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="True" CanUserReorder="False" CanUserResize="False"
                                                Visibility="{Binding Data.Encoding, Converter={StaticResource Encoding8b10bToCollapsedConverter}, Source={StaticResource proxy}}">
                                    <DataGridTextColumn.HeaderStyle>
                                        <Style TargetType="DataGridColumnHeader">
                                            <Setter Property="HorizontalContentAlignment"  Value="Center" />
                                        </Style>
                                    </DataGridTextColumn.HeaderStyle>
                                </DataGridTextColumn>

                                <!--todo: change… -->
                                <DataGridTextColumn Header="[0]" Binding="{Binding .Symbols[0].SymbolText, UpdateSourceTrigger=LostFocus}" CellStyle="{StaticResource CellPermissionStyle}" />
                                <DataGridTextColumn Header="[1]" Binding="{Binding .Symbols[1].SymbolText, UpdateSourceTrigger=LostFocus}" CellStyle="{StaticResource CellPermissionStyle}" />
                                <!-- … -->
                                <DataGridTextColumn Header="[15]" Binding="{Binding .Symbols[15].SymbolText, UpdateSourceTrigger=LostFocus}" CellStyle="{StaticResource CellPermissionStyle}" />


                            </DataGrid.Columns>

                        </DataGrid>

每个Block对象都有一个名为Symbols的属性,定义为Symbol类型的BindingList,以及其他一些属性。符号显示在带有标题[0],1等的列中 其他列中显示的其他块属性。例如。选中复选框,Reapeat,Name。

    public interface ISymbol
    {
        int Index { get; set; }
        bool ReadOnly { get; set; }
        string SymbolText { get; set; }
    }

    public class BlockBase : ObservableObject, IDataErrorInfo
    {

        public bool IsSelected
        {
            get { return _isSelected; }
            set 
            {
                if (value == _isSelected)
                    return;

                _isSelected = value;
                OnPropertyChanged("IsSelected");
                RaiseSelectionChangedEvent();
            }
        }

        public string Name { get; set; }
        public virtual BindingList<ISymbol> Symbols { get; set; }
        public BlockPermission Permission { get; set; }

        public int Repeat { get; set; }

    }


    public class Symbol : ObservableObject, ISymbol
    {
        DisplayFormat Format { get; set; }
        public int Index { get; set; }
        public virtual bool ReadOnly { get; set; }
        public virtual string SymbolText
        {
            get { return (Format == DisplayFormat.Binary) ? _binSymbol : _hexSymbol; 
        }
        set
        {
            // …  validate and set _binSymbol & _hexSymbol values
            OnPropertyChanged("SymbolText");
        }
    }

现在,我需要绑定每个符号的单元格&#39; IsEnabled&#39;属于Symbol&#39; ReadOnly&#39;属性。
我试图在DataGrid.Resources中将其定义为CellPermissionStyle,但我不知道如何在此级别上访问Symbol。

此外,用模板替换符号的所有重复DataGridTextColumn防御将会很好。

有人会帮助我吗?

1 个答案:

答案 0 :(得分:0)

我的研究刚刚证实,遗憾的是,对于适用于列子集的模板或样式,无法做到这一点。如Mishka建议的那样,将参数发送到样式或模板也是不可能的:(。

所以,我刚刚为我的16列中的每一列都采用'复制 - 粘贴 - 修改'单元格样式:

                                    <DataGridTextColumn Header="[0]" Binding="{Binding .Symbols[0].SymbolText, UpdateSourceTrigger=LostFocus}">                                        
                                    <DataGridTextColumn.CellStyle>
                                        <Style TargetType="DataGridCell">
                                            <Setter Property="Background" Value="{Binding .Symbols[0].ReadOnly, Converter={StaticResource SymbolReadOnlyToBrushConverter}}" />
                                            <Setter Property="IsEnabled" Value="{Binding .Symbols[0].ReadOnly, Converter={StaticResource SymbolReadOnlyToEnabledConverter}}" />
                                            <Setter Property="TextBlock.TextAlignment" Value="Center" />
                                        </Style>
                                    </DataGridTextColumn.CellStyle>
                                </DataGridTextColumn>

...

                                    <DataGridTextColumn Header="[15]" Binding="{Binding .Symbols[15].SymbolText, UpdateSourceTrigger=LostFocus}">
                                    <DataGridTextColumn.CellStyle>
                                        <Style TargetType="DataGridCell">
                                            <Setter Property="Background" Value="{Binding .Symbols[15].ReadOnly, Converter={StaticResource SymbolReadOnlyToBrushConverter}}" />
                                            <Setter Property="IsEnabled" Value="{Binding .Symbols[15].ReadOnly, Converter={StaticResource SymbolReadOnlyToEnabledConverter}}" />
                                            <Setter Property="TextBlock.TextAlignment" Value="Center" />
                                        </Style>
                                    </DataGridTextColumn.CellStyle>
                                </DataGridTextColumn>

是的,我知道,这个XAML看起来很难看,但它对我有用而没有对现有代码库进行重新设计的风险。

如果有人能在XAML中建议更好,更优雅的方式,我会很高兴。