WPF DataGridTemplateColumn MVVM DataContext属性可访问性问题

时间:2018-03-14 00:10:40

标签: wpf mvvm datagrid datagridtemplatecolumn

我试图访问每行内的布尔属性值,因此我可以使用它来设置按钮可见性,但是我无法使用DataGridTemplateColumn访问它。我能够将整个行对象转换为我传递给按钮命令的参数,但是我无法获得UseSetting值以传递给Visibility转换器。我尝试了如下图所示的文本列,但是当首次加载视图时,转换器似乎只会触发。使用断点我可以看到对UseSetting属性的后续更改不会触发转换器。我确实在DataGrid中使用的自定义类上正确设置了NotifyOfPropertyChange。

使用DataGridTemplateColumn时访问行属性的最佳方法是什么?我在DataGridTemplateColumn中创建自己的复选框而不是使用CheckboxColumn的原因是因为CheckboxColumn要求在检查之前选择行,并且我需要单击复选框才能检查。

要清楚,此视图背后没有代码。一切都在视图模型中,就像数据网格的项目源一样,它是自定义类的ObservableCollection" SharedSetting"我在下面列出。

<DataGrid MaxHeight="400" VerticalScrollBarVisibility="Auto" BorderThickness="1" CanUserAddRows="False" CanUserDeleteRows="False" BorderBrush="{DynamicResource AccentBaseColorBrush}" GridLinesVisibility="Horizontal"  AutoGenerateColumns="False"  ItemsSource="{Binding SharedSettings, NotifyOnSourceUpdated=True}">
<DataGrid.ColumnHeaderStyle>
    <Style TargetType="{x:Type DataGridColumnHeader}" >
        <Setter Property="FontWeight"  Value="Bold" />
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="FontSize" Value="10" />
    </Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
    <DataGridTextColumn Width="250" Header="Setting" Binding="{Binding Setting}" />
    <DataGridTextColumn Width="300" Header="Value" ElementStyle="{StaticResource WrapText}" Binding="{Binding Value}" />
    <DataGridTextColumn Width="75" Header="Use Setting" Binding="{Binding UseSetting, Mode=TwoWay}" x:Name="stackRowUseSetting" />
    <DataGridTemplateColumn Width="50" >
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Grid Width="30" Height="30" x:Name="stackRow2">
                    <Button Background="Transparent" Foreground="{StaticResource AccentColorBrush}" ToolTip="Do Not Use Setting"  Visibility="{Binding ElementName=stackRowUseSetting, Path=Binding, Converter={StaticResource TrueToVisibleConverter}}"  BorderThickness="0" Margin="0,0,0,0" DataContext="{Binding ElementName=MainGrid, Path=DataContext}" Command="{Binding ToggleUseSettingCommand}" CommandParameter="{Binding ElementName=stackRow2,Path=DataContext}">
                        <iconPacks:PackIconMaterial Kind="CheckCircleOutline" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0"    />
                    </Button>
                    <Button Background="Transparent" Foreground="{StaticResource AccentColorBrush}" ToolTip="Use Setting" Visibility="{Binding ElementName=stackRowUseSetting, Path=Binding, Converter={StaticResource FalseToVisibleConverter}}" BorderThickness="0" Margin="0,0,0,0" DataContext="{Binding ElementName=MainGrid, Path=DataContext}" Command="{Binding ToggleUseSettingCommand}" CommandParameter="{Binding ElementName=stackRow2,Path=DataContext}">
                        <iconPacks:PackIconMaterial Kind="CheckboxBlankCircleOutline" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0"    />
                    </Button>

                </Grid>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>


</DataGrid.Columns>
</DataGrid>

此外,上面的XAML正是我现在所拥有的。这里有一些项目很可能是多余的而且不需要。我添加并删除了许多试图使其工作的东西,目前它有点草率。

这是带有INotifyPropertyChanged

的SharedSetting类
public class SharedSetting : INotifyPropertyChanged
{
    private bool _useSetting;
    private object _o;
    private string _value;
    private string _setting;
    private string _group;

    public SharedSetting(string groupName, string settingName, string settingValue, object value, bool use=false)
    {
        Group = groupName;
        Setting = settingName;
        Value = settingValue;
        Object = value;
        UseSetting = use;
    }
    public SharedSetting()
    {

    }

    public string Group
    {
        get { return _group; }
        set
        {
            _group = value;
            NotifyPropertyChanged();
        }
    }

    public string Setting
    {
        get { return _setting; }
        set
        {
            _setting = value;
            NotifyPropertyChanged();
        }
    }

    public string Value
    {
        get { return _value; }
        set
        {
            _value = value;
            NotifyPropertyChanged();
        }
    }

    public object Object
    {
        get { return _o; }
        set
        {
            _o = value;
            NotifyPropertyChanged();
        }
    }

    public bool UseSetting
    {
        get { return _useSetting; }
        set
        {
            _useSetting = value;
            NotifyPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

这是其中一个转换器。

public sealed class TrueToVisibleConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var flag = false;
        if (value is bool)
        {
            flag = (bool) value;
        }
        var visibility = (object) (Visibility) (flag ? 0 : 2);
        return visibility;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Visibility)
        {
            var visibility = (object) ((Visibility) value == Visibility.Visible);
            return visibility;
        }
        return (object) false;
    }
}

更新3/14/18

要解决下面提供的关于删除我的DataContext设置并使用与所有其他列一样的属性的第一个答案,这不起作用。这是我很久以前尝试的第一件事,只是为了得知DataGridTemplateColumn没有像其他列那样继承行的数据上下文(我昨天在下面的评论中感到沮丧的原因)。我已经包含了一个屏幕截图,显示了智能感知错误,说明该属性不存在,当它的使用方式与上面的列相同时。

Showing that it isn't as simple as using it like a DataGridTextColumn

1 个答案:

答案 0 :(得分:0)

您为DataContext竖立了ButtonDataContext="{Binding ElementName=MainGrid, Path=DataContext}"是错误的,因此请将其删除并绑定到DataGridTextColumn中的属性。并且Command与不在SharedSetting中的命令的绑定使用ElementName(正如您对DataContext所做的那样)或RelativeSource
更新:
应该工作,但也可以尝试

<Button Visibility="{Binding DataContext.UseSetting, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Converter={StaticResource TrueToVisibleConverter}}" />