简体   繁体   English

WPF GridViewColumn CellTemplate c#的动态更改

[英]WPF Dynamic change of GridViewColumn CellTemplate c#

I'm trying to learn something about the ListView and now I'm solving this problem: 我正在尝试学习有关ListView的知识,现在我正在解决此问题:

I have a listview defined in the behindcode. 我在backcode中定义了一个listview。 I would like to change gridviewcolumn celltemplate dynamically. 我想动态更改gridviewcolumn celltemplate。 For example by the use of checkbox or button, or other. 例如,通过使用复选框或按钮或其他。 Is it even possible? 可能吗

Definition of my ListView is here: 我的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);

I would like to change CellTemplate of colStack to templateStack1 in runtime by the checking a checkbox or button click. 我想在运行时通过选中复选框或按钮单击将colStack的CellTemplate更改为templateStack1。

Thank you for any of your ideas. 谢谢您的任何想法。

You can make use of DataTrigger in order to change dynamically the ContentTemplate of your columns. 您可以使用DataTrigger来动态更改列的ContentTemplate Here is an example using XAML: 这是使用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>

And the codebehind file: 和代码隐藏文件:

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; }
    }
}

The result is that whenever you toggle the checkbox's IsChecked property the content template of the cell for the given column changes too. 结果是,每当您切换复选框的IsChecked属性时,给定列的单元格内容模板也会更改。

EDIT How to do it with code behind only 编辑如何使用仅背后的代码来做到这一点

For completness sake here is how you can achieve this with code behind only: 为了完善起见,这里是仅使用后面的代码即可实现此目的的方法:

    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;

IMHO this way looks a little bit messy, but the decision is yours =) 恕我直言,这种方式看起来有点混乱,但决定权由您决定=)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM