WPF GridViewColumn CellTemplate c#

时间:2018-07-24 14:13:20

标签: c# wpf dynamic gridviewcolumn celltemplate

我正在尝试学习有关ListView的知识,现在我正在解决此问题:

我在背后的代码中定义了一个列表视图。我想动态更改gridviewcolumn celltemplate。例如,通过使用复选框或按钮或其他。甚至有可能吗?

我的ListView的定义在这里:

        lvUsers.ItemsSource = LoadListViewData();

        GridView gridview = new GridView();
        lvUsers.View = gridview;

        DataTemplate templateCheck = new DataTemplate();
        FrameworkElementFactory factoryContentControlCheck = new FrameworkElementFactory(typeof(VsCheckBox));
        factoryContentControlCheck.SetValue(VsCheckBox.MarginProperty, new Thickness(0, 0, 0, 0));

        DataTemplate templateBorder = new DataTemplate();
        FrameworkElementFactory factoryContentControlBorder = new FrameworkElementFactory(typeof(Border));
        factoryContentControlBorder.SetValue(Border.MarginProperty, new Thickness(0, 0, 10, 0));
        factoryContentControlBorder.SetValue(Border.WidthProperty, Width = 10);
        factoryContentControlBorder.SetValue(Border.HeightProperty, Height = 10);
        factoryContentControlBorder.SetValue(Border.BackgroundProperty, Brushes.Red);            

        DataTemplate templateAge = new DataTemplate();
        FrameworkElementFactory factoryContentControlAge = new FrameworkElementFactory(typeof(ContentControl));
        factoryContentControlName.SetValue(ContentControl.MarginProperty, new Thickness(0, 0, 10, 0));
        factoryContentControlAge.SetValue(ContentControl.VerticalAlignmentProperty, VerticalAlignment.Center);
        factoryContentControlAge.SetValue(ContentControl.HorizontalAlignmentProperty, HorizontalAlignment.Right);
        factoryContentControlAge.SetBinding(ContentControl.ContentProperty, new Binding("Age"));

        DataTemplate templateStack = new DataTemplate();
        FrameworkElementFactory factoryContentControlStack = new FrameworkElementFactory(typeof(StackPanel));
        factoryContentControlStack.SetValue(StackPanel.MarginProperty, new Thickness(10, 0, 0, 0));
        factoryContentControlStack.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
        factoryContentControlStack.SetValue(StackPanel.VerticalAlignmentProperty, VerticalAlignment.Center);
        factoryContentControlStack.AppendChild(factoryContentControlCheck);
        factoryContentControlStack.AppendChild(factoryContentControlBorder);
        templateStack.VisualTree = factoryContentControlStack;

        DataTemplate templateStack1 = new DataTemplate();
        FrameworkElementFactory factoryContentControlStack1 = new FrameworkElementFactory(typeof(StackPanel));
        factoryContentControlStack1.SetValue(StackPanel.MarginProperty, new Thickness(10, 0, 0, 0));
        factoryContentControlStack1.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
        factoryContentControlStack1.SetValue(StackPanel.HorizontalAlignmentProperty, HorizontalAlignment.Right);
        factoryContentControlStack1.SetValue(StackPanel.VerticalAlignmentProperty, VerticalAlignment.Center);
        factoryContentControlStack1.AppendChild(factoryContentControlAge);
        templateStack1.VisualTree = factoryContentControlStack1;

        GridViewColumn colStack = new GridViewColumn();
        colStack.Header = "Stack";
        colStack.CellTemplate = templateStack;

        gridview.Columns.Add(colStack);

我想在运行时通过选中复选框或单击按钮,将colStack的CellTemplate更改为templateStack1。

谢谢您的任何想法。

1 个答案:

答案 0 :(得分:0)

您可以使用DataTrigger来动态更改列的ContentTemplate。这是使用XAML的示例:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <CheckBox x:Name="TemplateChanger" Content="Change template"
                  IsChecked="{Binding IsChecked}"/>
        <DataGrid x:Name="DataGrid" Grid.Row="1" AutoGenerateColumns="False"
                  ItemsSource="{Binding Items}">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="My column" IsReadOnly="True">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Foo}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>

                    <DataGridTemplateColumn.CellStyle>
                        <Style TargetType="DataGridCell">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding DataContext.IsChecked, RelativeSource={RelativeSource AncestorType=DataGrid}}" Value="True">
                                    <Setter Property="ContentTemplate">
                                        <Setter.Value>
                                            <DataTemplate>
                                                <TextBlock Text="fsdfsdf"/>
                                            </DataTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </DataGridTemplateColumn.CellStyle>

                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

以及代码隐藏文件:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using WpfApp.Annotations;

namespace WpfApp
{
    /// <summary>
    ///     Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : INotifyPropertyChanged
    {
        private bool _isChecked;

        public MainWindow()
        {
            InitializeComponent();

            Items.Add(new Item {Foo = "Foo1"});
            Items.Add(new Item {Foo = "Foo2"});
            Items.Add(new Item {Foo = "Foo3"});
            Items.Add(new Item {Foo = "Foo4"});
        }

        public bool IsChecked
        {
            get => _isChecked;
            set
            {
                _isChecked = value;
                OnPropertyChanged();
            }
        }

        public ObservableCollection<Item> Items { get; } = new ObservableCollection<Item>();
        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class Item
    {
        public string Foo { get; set; }
    }
}

结果是,每当切换复选框的IsChecked属性时,给定列的单元格内容模板也会更改。

编辑如何仅使用后面的代码

为了完整起见,这里是仅使用后面的代码即可实现此目标的方法:

    var datagrid = new DataGrid {AutoGenerateColumns = false};
    Grid.SetRow(datagrid,1);
    RootGrid.Children.Add(datagrid);

    var templateColumn = new DataGridTemplateColumn
    {
        Header = "My column",
        IsReadOnly = true
    };
    var cellTemplate = new DataTemplate();
    var factory = new FrameworkElementFactory(typeof(TextBlock));
    factory.SetBinding(TextBlock.TextProperty, new Binding("Foo"));

    var style = new Style(typeof(DataGridCell));
    var trigger = new DataTrigger();
    var triggerBinding = new Binding("DataContext.IsChecked")
    {
        RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DataGrid), 1)
    };
    trigger.Binding = triggerBinding;
    trigger.Value = true;
    var triggerSetter = new Setter {Property = ContentTemplateProperty};
    var triggerTemplate = new DataTemplate();
    var anotherFactory = new FrameworkElementFactory(typeof(TextBlock));
    anotherFactory.SetValue(TextBlock.TextProperty,"lol");
    triggerTemplate.VisualTree = anotherFactory;
    triggerSetter.Value = triggerTemplate;
    trigger.Setters.Add(triggerSetter);
    style.Triggers.Add(trigger);

    templateColumn.CellStyle = style;

    cellTemplate.VisualTree = factory;
    templateColumn.CellTemplate = cellTemplate;
    datagrid.Columns.Add(templateColumn);

    datagrid.ItemsSource = Items;

这种方式的恕我直言看起来有些混乱,但决定权由您决定=)