【问题标题】:WPF DataTemplate do not call getWPF DataTemplate 不调用 get
【发布时间】:2017-04-19 18:48:03
【问题描述】:

我必须使用 2 种不同的方式来设置值。 Screenshot

  1. 如果没有 DataTemplate(参数类型),则调用 set 方法。此列中所有元素的类型相同。
  2. 使用 DataTemplate (Value) 不会调用 set 方法。我必须使用不同的模板,因为此列中的值来自不同的类型。

mainwindow.xaml 代码

<Window x:Class="WpfGridTest.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"
    xmlns:data="clr-namespace:WpfGridTest.MVVM"
    xmlns:system="clr-namespace:WpfGridTest.Common"
    mc:Ignorable="d"
    Title="MainWindow" Height="300" Width="450"
    FontSize="12">

<Window.DataContext>
    <data:ParameterListViewModel/>    
</Window.DataContext>

<Grid DataContext="{Binding ParameterList}">
    <Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <ToolBar Grid.Row="0" Background="LightGray">
        </ToolBar>

        <DataGrid Grid.Row="1" x:Name="dataGrid" ItemsSource="{Binding}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                  AutoGenerateColumns="False" CanUserAddRows="False">

            <DataGrid.Resources>
                <DataTemplate x:Key="StringTemplate">
                    <TextBox Text="{Binding Value, Mode=TwoWay}" Margin="2" 
                             Background="GreenYellow" Foreground="Black" />
                </DataTemplate>
                <DataTemplate x:Key="EnumTemplate">
                    <ComboBox Margin="2" ItemsSource="{Binding EnumList, Mode=TwoWay}" DisplayMemberPath="Name" SelectedValue="{Binding Value}" SelectedValuePath="Value" 
                              Background="GreenYellow" Foreground="Black" />
                </DataTemplate>
                <DataTemplate x:Key="NumberTemplate">
                    <TextBox Margin="2" Text="{Binding Value, Mode=TwoWay}" 
                             Background="GreenYellow" Foreground="Black" TextAlignment="Right" />
                </DataTemplate>
            </DataGrid.Resources>

            <DataGrid.Columns>
                <DataGridTextColumn x:Name="Name" Header="Parameter name" Binding="{Binding Name}"/>

                <DataGridComboBoxColumn x:Name="Type" Header="Parameter type" SelectedValueBinding="{Binding Type}"
                                        ItemsSource="{Binding Source={x:Static data:ParameterListViewModel.GetListOfParameterTypes}}"/>

                <DataGridTemplateColumn Header="Value">
                    <DataGridTemplateColumn.CellTemplateSelector>
                        <system:ParameterTypeTemplateSelector 
                            EnumTemplate="{StaticResource EnumTemplate}" 
                            StringTemplate="{StaticResource StringTemplate}"
                            NumberTemplate="{StaticResource NumberTemplate}"/>
                    </DataGridTemplateColumn.CellTemplateSelector>

                </DataGridTemplateColumn>

            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Grid>

ParameterModel.cs

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using WpfGridTest.Common;

namespace WpfGridTest.MVVM
{
    public enum ParameterType
    {
        UINT16,
        ENUM16,
        BIT_ENUM16,
        FLOAT,
        DATE,
        STRING
    }

    public class EnumItem
    {
        public string Name { get; set; }
        public int Value { get; set; }
    }

    public class Parameter : ViewModelBase
    {
        public Parameter()
        {
        }

        public Parameter(string name, ParameterType type)
        {
            Name = name;
            Type = type;
        }

        public string Name { get; set; }
        public ParameterType Type { get; set; }
        public List<EnumItem> EnumList { get; set; }
        public object Value { get; set; }

        public override void OnLoaded()
        {
            throw new NotImplementedException();
        }

        public override void OnUnloaded()
        {
            throw new NotImplementedException();
        }
    }
 }

ParameterViewModel.cs

   using System.Collections.Generic;
    using WpfGridTest.Common;

    namespace WpfGridTest.MVVM
    {
        public class ParameterViewModel : ViewModelBase
        {
            #region Properties
            private string name;
            public string Name
            {
                get { return name; }
                set
                {
                    name = value;
                    OnPropertyChanged (nameof (Name));
                }
            }

            private ParameterType type;
            public ParameterType Type
            {
                get { return type; }
                set { type = value; OnPropertyChanged (nameof (Type)); }
            }

            private List<EnumItem> enumlist; 
            public List<EnumItem> EnumList
            {
                get { return enumlist; }
                set { enumlist = value; OnPropertyChanged(nameof(EnumList)); 
 }           }

            private object _value;
            public object Value
            {
                get { return _value; }
                set { _value = value; OnPropertyChanged(nameof(Value)); }
            }
        }
    }

ParameterListViewModel.cs

公共类 ParameterListViewModel : ViewModelBase { #region 构造函数

public ParameterListViewModel()
{
    List<EnumItem> list1 = new List<EnumItem>
    {
        new EnumItem {Name = "Item 1.1", Value = 1},
        new EnumItem {Name = "Item 1.2", Value = 2},
    };

    ParameterList = new ObservableCollection<ParameterViewModel>();
    ParameterList.Add (new ParameterViewModel { Name = "Enum 1", Type = ParameterType.ENUM16, Value=1, EnumList = list1 }) ;
    ParameterList.Add (new ParameterViewModel { Name = "String", Type = ParameterType.STRING, Value="Test String" });
    ParameterList.Add (new ParameterViewModel { Name = "Uint",   Type = ParameterType.UINT16, Value=123 });
}

private ObservableCollection<ParameterViewModel> parameterlist; 
public ObservableCollection<ParameterViewModel> ParameterList
{
    get { return parameterlist;  }
    set
    {
        parameterlist = value;
        OnPropertyChanged (nameof(ParameterList));
    }
}

public static IEnumerable<ParameterType> GetListOfParameterTypes => Enum.GetValues(typeof(ParameterType)).Cast<ParameterType>();
}

至少还有 TemplateSelector 类

namespace WpfGridTest.Common
{
    public class ParameterTypeTemplateSelector : DataTemplateSelector
    {
        public DataTemplate EnumTemplate       { get; set; }
        public DataTemplate NumberTemplate     { get; set; }
            public DataTemplate StringTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            //Parameter parameter = item as Parameter;
            ParameterViewModel parameter = item as ParameterViewModel;

            if (parameter != null)
            {
                if ((parameter.Type == ParameterType.ENUM16) || (parameter.Type == ParameterType.BIT_ENUM16))
                    return EnumTemplate;
                else if ((parameter.Type == ParameterType.STRING))
                    return StringTemplate;
                else
                    return NumberTemplate;
            }
            else
                return base.SelectTemplate(item, container);
        }
    }
}

【问题讨论】:

  • 不错的代码转储问题在哪里?
  • 你是对的。如果我更改值,则不会调用 ParameterViewModel.cs 中“值”的设置属性。我做错了什么?
  • 编辑问题,人们不会在 cmets 中寻找更正

标签: wpf xaml


【解决方案1】:

https://msdn.microsoft.com/en-us/library/system.windows.controls.datagridtemplatecolumn.celltemplateselector(v=vs.110).aspx

获取或设置确定使用哪个模板来显示未处于编辑模式的单元格内容的对象。

【讨论】:

  • 我不明白。我有一个 CellTemplateSelector。请参阅公共类 ParameterTypeTemplateSelector :DataTemplateSelector
  • 就是这样。 CellTemplate 是只读的。当单元格获得焦点时,它会将模板更改为 CellEditingTemplate。看这里:msdn.microsoft.com/en-us/library/…
  • 谢谢,现在可以了。 但是如何将 CellTemplateSelector 和 CellEditingTemplateSelector 用于同一个 DataGridTemplateColumn?如果我只使用 CellEditingTemplateSelector,则不会显示任何值。如果我同时使用两者,则不会调用 Setter。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
相关资源
最近更新 更多