【问题标题】:Wpf - Issue with visibility of ToggleButtons inside a cell of a datagridWpf - 数据网格单元格内切换按钮的可见性问题
【发布时间】:2013-09-26 12:52:11
【问题描述】:

我目前正在开发一个 WPF 应用程序,该应用程序包含一个包含 3 列的数据网格,其中包含 ToggleButtons,其代码如下

<DataGridTemplateColumn Header="Closed" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ToggleButton>
                <ToggleButton.Content>
                    ...
                </ToggleButton.Content>
            </ToggleButton>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Checked" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
                <ToggleButton Visibility="{Binding Path=IsClosedProperty, Converter={StaticResource toggleButtonVisibilityConverter}}">
                        <ToggleButton.Content>
                            ...
                        </ToggleButton.Content>
                </ToggleButton>
            </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Active" Width="60">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ToggleButton Visibility="{Binding Path=IsCheckedProperty, Converter={StaticResource toggleButtonVisibilityConverter}}">
                <ToggleButton.Content>
                    ...
                </ToggleButton.Content>
            </ToggleButton>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

toggleButtonVisibilityConverter的代码如下

public class ToggleButtonVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value is bool && ((bool)value) ? Visibility.Visible : Visibility.Hidden;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

应用程序应该这样工作,当单击 Closed 列中的一行的 ToggleButton 时,该行的 Checked 列中的 ToggleButton 变得可见(即调用 toggleButtonVisibilityConverter)。此外,当单击Checked 列中某一行的ToggleButton 时,该行的Active 列中的ToggleButton 变为可见。当相应的 ToggleButtons 未被点击时,它们应该隐藏在相同的层次结构中。

IsClosedPropertyIsCheckedProperty 是 ViewModel 的布尔属性,分别在单击 ClosedChecked 切换按钮时设置为 true。

【问题讨论】:

  • 我不知道如何在点击ToggleButton时调用转换器。

标签: wpf xaml datagrid converter


【解决方案1】:

保存数据的类

public class GridToggleButtonItem
{
    private bool _isClosedProperty;

    public bool IsClosedProperty
    {
        get { return _isClosedProperty; }
        set { _isClosedProperty = value; }
    }

    private bool _isCheckedProperty;

    public bool IsCheckedProperty
    {
        get { return _isCheckedProperty; }
        set { _isCheckedProperty = value; }
    }
}

具有要绑定到数据网格的项目集合的 ViewModel

public class GridToggleButtonViewModel
{
    public List<GridToggleButtonItem> Items { get; set; }

    public GridToggleButtonViewModel()
    {
        Items = new List<GridToggleButtonItem>()
        {
            new GridToggleButtonItem() { IsCheckedProperty = false, IsClosedProperty = false},
            new GridToggleButtonItem() { IsCheckedProperty = false, IsClosedProperty = false},
            new GridToggleButtonItem() { IsCheckedProperty = false, IsClosedProperty = false},
            new GridToggleButtonItem() { IsCheckedProperty = false, IsClosedProperty = false},
            new GridToggleButtonItem() { IsCheckedProperty = false, IsClosedProperty = false}
        };
    }
}

绑定到视图模型的 XAML 代码

<Window x:Class="StackOverFlowQ.GridToggleButton"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:StackOverFlowQ"
    Title="GridToggleButton" Height="500" Width="500">
<Window.DataContext>
    <local:GridToggleButtonViewModel></local:GridToggleButtonViewModel>
</Window.DataContext>
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>

    <Style TargetType="{x:Type ToggleButton}">
        <Setter Property="Margin" Value="3"></Setter>            
        <Style.Triggers>
            <Trigger Property="IsChecked" Value="True">
                <Setter Property="FontWeight" Value="Bold"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<StackPanel>
    <DataGrid ItemsSource="{Binding Path=Items}" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="Cell" CanUserAddRows="False" >
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Closed" Width="100">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ToggleButton Content="Closed" IsChecked="{Binding Path=IsClosedProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></ToggleButton>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Checked" Width="100">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ToggleButton Content="Checked" Visibility="{Binding Path=IsClosedProperty, Converter={StaticResource ResourceKey=BooleanToVisibilityConverter}}" IsChecked="{Binding Path=IsCheckedProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></ToggleButton>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Active" Width="100">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ToggleButton Content="Active" Visibility="{Binding Path=IsCheckedProperty, Converter={StaticResource ResourceKey=BooleanToVisibilityConverter}}"></ToggleButton>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</StackPanel>

【讨论】:

    【解决方案2】:
    <Grid>
                <Grid.Resources>
                    <FrameworkElement x:Key="ProxyElement" DataContext="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}}" />
                </Grid.Resources>
                <ContentControl Content="{StaticResource ProxyElement}" Visibility="Collapsed" />
                    <DataGrid 
                              ItemsSource="{Binding SomeData}">
                        <DataGrid.Columns>
                            <DataGridTemplateColumn IsReadOnly="True">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <Image MaxWidth="16"
                                               MaxHeight="16"
                                               Source="/abc.png" />
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>
                            <DataGridTemplateColumn MinWidth="80" >
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <TextBlock Foreground="Black" Text="{Binding Name}" />
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>                            
                            </DataGridTemplateColumn>
                            <DataGridTextColumn MinWidth="64"
                                                Binding="{Binding Category}"
                                                Foreground="Black"
                                                IsReadOnly="True"
                                                Visibility="{Binding Path=DataContext.IsCategoryColumnVisible,
                                                                     Source={StaticResource ProxyElement},
                                                                     Converter={StaticResource BooleanVisibilityConverter}}" />
                            <DataGridTextColumn MinWidth="64"
                                                Binding="{Binding Size}"
                                                Foreground="Black"
                                                IsReadOnly="True"
                                                Visibility="{Binding Path=DataContext.IsSizeColumnVisible,
                                                                     Source={StaticResource ProxyElement},
                                                                     Converter={StaticResource BooleanVisibilityConverter}}" />
                        </DataGrid.Columns>
                    </DataGrid>               
            </Grid>
    

    DataGridColumns 不是可视树的一部分,因此您的绑定将不起作用。这是我的解决方案。

    1. 创建一个代理对象并将其 DataContext 绑定到正确的对象,该对象应位于 DataContext(您的 ViewModel)中。
    2. 将其放入 ContentControl 并使其隐藏。
    3. 使用您的代理对象作为绑定源。

    【讨论】:

    • AncestorType=ListBoxItem ?
    • 它是 ListBoxItem 的 DataTenplate,您可以相应地更改您的绑定。将其替换为您的窗口或其他任何东西,它可以在 DataContext 中找到您的 ViewModel。
    猜你喜欢
    • 2012-08-15
    • 2011-12-15
    • 2012-05-31
    • 2012-10-04
    • 2011-06-14
    • 1970-01-01
    • 2021-12-30
    • 2013-10-14
    • 1970-01-01
    相关资源
    最近更新 更多