Wpf - 在数据网格的单元格内可见ToggleButtons的问题

时间:2013-09-21 03:18:04

标签: wpf xaml datagrid converter

我目前正在开发一个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 toggleButtons时设置为true。

2 个答案:

答案 0 :(得分:1)

<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不是Visual Tree的一部分,因此您的绑定将不起作用。这是我的解决方案。

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

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

具有要绑定到datagrid的项集合的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}
        };
    }
}

绑定到viewmodel的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>