无法将cellValuePresenter/TypeConverter应用于XamDataGrid单元 [英] Cannot apply cellValuePresenter/TypeConverter to XamDataGrid cells

查看:68
本文介绍了无法将cellValuePresenter/TypeConverter应用于XamDataGrid单元的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我也在Infragistics上问过 ,但是不知道如何在此处格式化我的代码,所以在这里它的格式正确.

I also asked this at Infragistics, but don't know how to format my code there, so here it is properly formatted.

我的目标是提供一个结构化数据表,其中每个单元格的文本都使用多种颜色.我有一个typeconverter,它将存储在自定义类中的数据转换为包含几个具有不同颜色的文本元素的标签或文本块.数据在数据表中提供(任何可行的方法都可以),并且每个值都正确应用于单元格.

My goal is to present a table of structured data with the text of each cell using multiple colors. I have a typeconverter which will convert the data stored in a custom class to a label or textblock containing several text elements with different colors. The data is provided in a datatable (any method that works will be fine) and each value is correctly applied to a cell.

问题在于,它使用ToString方法代替了我的TypeConverter,我重写了它,因此我知道模型正确的模型数据是逐格映射到网格单元上的.我正在使用的ControlTemplate属性也没有应用,这告诉我ControlTemplate没有被使用.

The problem is that instead of using my TypeConverter it uses the ToString method, which I override so I know the model correct model data is mapped on the grid cell by cell. Also the ControlTemplate properties that I'm using are not applied, which tells me the ControlTemplate is not being used.

一个问题是,在数据网格中可能无法包含不同字母具有不同颜色的文本.如果是这样,还有另一种方法可以完成,同时仍然具有良好的用户体验,并将设计保留在xaml文件中(使用网格很难做到).

A concern is it may not be possible to have text where different letters have different colors in a datagrid. If so, is there another way that can be done while still having a good user experience and keeping the design in the xaml file (which is hard with a grid).

据我了解,我的代码应定义一个自定义的CellValuePresenter,有人可以帮助我应用它吗?

As I understand it my code should define a custom CellValuePresenter, can anyone please help me to apply it?

我在这里发布我的相关代码.大部分都是模糊的,所以请不要专注于拼写错误.

I'm posting my relevant code here. Most of it is obfuscated so please don't focus on spelling errors.

  <Window x:Class="ViewName"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="clr-namespace:LocalNamespace"
          xmlns:ViewModel="clr-namespace:LocalNamespace.ViewModel"
          xmlns:model="clr-namespace:LocalNamespace.Model"
          xmlns:igDP="http://infragistics.com/DataPresenter"
          >
      <Window.Resources>
          <local:Converter x:Key="converter" />
          <ViewModel:ViewModelLocator x:Key="viewModelLocator" />
          <Style TargetType="{x:Type igDP:CellValuePresenter}" x:Key="cellTemplate" x:Name="cellTemplate" >
              <Setter Property="Template">
                  <Setter.Value>
                      <ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}">
                          <Label 
                              Content="{Binding Converter={StaticResource converter}}"
                              Width="200"
                              MaxWidth="600"
                              MinHeight="20"
                              />
                      </ControlTemplate>
                  </Setter.Value>
              </Setter>
          </Style>
      </Window.Resources>
        <StackPanel Name="stackPanel">
            <igDP:XamDataGrid Name="DifferenceGrid" DataSource="{Binding Source={StaticResource viewModelLocator}, Path=ViewModel.Model}" 
                              ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible">
                <igDP:XamDataGrid.FieldLayouts>
                    <igDP:FieldLayout>
                        <igDP:FieldLayout.Fields>
                            <igDP:Field>
                                <igDP:Field.Settings>
                                    <igDP:FieldSettings 
                                        CellValuePresenterStyle="{StaticResource cellTemplate}">
                                    </igDP:FieldSettings>
                                </igDP:Field.Settings>
                            </igDP:Field>
                        </igDP:FieldLayout.Fields>
                    </igDP:FieldLayout>
                </igDP:XamDataGrid.FieldLayouts>
            </igDP:XamDataGrid>
        </StackPanel>
  </Window>

    class ViewModelLocator
    {
        private static ViewModel viewModel = new ViewModel();

        public ViewModel ViewModel
        {
            get
            {
                return viewModel;
            }
        }
    }

  public class ViewModel
    {
        private DataTable model;

        public DataTable Model
        {
            get
            {
                return this.model;
            }

            private set
            {
                this.model = value;
            }
        }

    [global::System.ComponentModel.TypeConverter(typeof(Model.CustomClass))]
    public class Converter : TypeConverter, IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (this.CanConvertTo(targetType))
            {
                return this.ConvertTo(value);
            }
            else
            {
                return null;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (this.CanConvertFrom(targetType))
            {
                return this.ConvertFrom(value);
            }
            else
            {
                return null;
            }
        }

        public new bool CanConvertFrom(Type sourceType)
        {
            // Textboxes don't need to be converted back.
            return sourceType == typeof(Model.CustomClass);
        }

        public new bool CanConvertTo(Type destinationType)
        {
            return destinationType == typeof(Model.CustomClass);
        }

        public object ConvertTo(object value)
        {
            return this.ConvertCustomClassToTextBlock(value);
        }

        public new object ConvertFrom(object value)
        {
            return this.ConvertCustomClassToTextBlock(value);
        }

        private object ConvertCustomClassToTextBlock(object value)
        {
            TextBlock text = new TextBlock();
            Label cell = new Label();

      // Construct the TextBlock.

      cell.Context = text;
      return text; // Or cell, whatever works.
    }
  }

推荐答案

XamDataGrid单元格包含编辑器,对于应以文本形式显示的值,编辑器为XamTextEditor.

XamDataGrid cells contain editors and for values that should be presented as text, editor is XamTextEditor.

您必须修改XamTextEditor的模板,并在以下代码中提供自己的模板:

You must modify template of XamTextEditor and provide your own like in the following code:

<Window x:Class="XamDataGridApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:igDP="http://infragistics.com/DataPresenter"
        xmlns:igEditors="http://infragistics.com/Editors"
        xmlns:local="clr-namespace:XamDataGridApp"
        Title="Colorful XamDataGrid" SizeToContent="WidthAndHeight">
    <igDP:XamDataGrid FieldLayoutInitialized="OnFieldLayoutInitialized">
        <igDP:XamDataGrid.DataSource>
            <!-- Replace this with your data source. -->
            <local:DataSourceMock/>
        </igDP:XamDataGrid.DataSource>
        <igDP:XamDataGrid.Resources>
            <local:XamTextEditorConverter x:Key="XamTextEditorConverter" x:Shared="True"/>
            <Style TargetType="igEditors:XamTextEditor" BasedOn="{StaticResource {x:Type igEditors:XamTextEditor}}">
                <Style.Setters>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type igEditors:XamTextEditor}">
                                <Border x:Name="MainBorder" 
                                        Background="{TemplateBinding Background}"
                                        BorderBrush="{TemplateBinding BorderBrush}"
                                        BorderThickness="{TemplateBinding BorderThickness}"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
                                    <ContentPresenter
                                        Margin="{TemplateBinding Padding}"
                                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                        <ContentPresenter.Content>
                                            <MultiBinding Converter="{StaticResource XamTextEditorConverter}">
                                                <Binding Path="DisplayText" RelativeSource="{RelativeSource TemplatedParent}"/>
                                                <Binding RelativeSource="{RelativeSource TemplatedParent}"/>
                                            </MultiBinding>
                                        </ContentPresenter.Content>
                                    </ContentPresenter>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style.Setters>
            </Style>
            <Style TargetType="igEditors:XamTextEditor" x:Key="CustomClassXamTextEditorStyle" x:Shared="True" BasedOn="{StaticResource {x:Type igEditors:XamTextEditor}}">
                <Setter Property="ValueToDisplayTextConverter" Value="{x:Static local:CustomClassToStringConverter.Instance}"/>
                <Setter Property="ValueToTextConverter" Value="{x:Static local:CustomClassToStringConverter.Instance}"/>
            </Style>
        </igDP:XamDataGrid.Resources>
    </igDP:XamDataGrid>
</Window>

以下IMultiValueConverter用于强制生成XamTextEditor内容:

Following IMultiValueConverter is used to generate XamTextEditor content imperatively:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using Infragistics.Windows.DataPresenter;
using Infragistics.Windows.Editors;

namespace XamDataGridApp
{
    class XamTextEditorConverter : IMultiValueConverter
    {
        private static readonly IList<Brush> colors = new Brush[] { Brushes.Red, Brushes.Green, Brushes.Blue };

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var displayText = (string)values[0] ?? string.Empty;

            // Context that can be used for custom coloring.
            var editor = (XamTextEditor)values[1];
            var dataItemPresenter = editor.Host as DataItemPresenter;

            // Context that can be used for custom coloring.
            var dataValue = editor.Value;
            var dataItem = dataItemPresenter != null ? dataItemPresenter.Record.DataItem : null;

            var textBlock = new TextBlock()
            {
                TextWrapping = editor.TextWrapping,
                TextAlignment = editor.TextAlignment
            };

            for (int i = 0; i < displayText.Length; ++i)
                textBlock.Inlines.Add(new Run(displayText[i].ToString()) { Foreground = colors[i % colors.Count] });

            return textBlock;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

XamTextEditor模板中的

ContentPresenter必须与编辑器的DisplayText属性进行数据绑定,因为XamDataGrid单元是虚拟化的,并且通过绑定,我们指示XamDataGrid在单元虚拟化开始时(当CellValuePresenter重用于显示另一个值时)重新生成ContentPresenter内容.另外,由于数据绑定,即使在XamDataGrid外部更改内容,也将重新生成内容.

ContentPresenter inside XamTextEditor template must be data-bound to editor's DisplayText property because XamDataGrid cells are virtualized and with the binding we instruct XamDataGrid to regenerate ContentPresenter content when cell virtualization kicks in (when CellValuePresenter gets reused to present another value). Also, because of the data-binding, content will be regenerated even if it is changed outside of XamDataGrid.

MultiBinding用于传递上下文(XamTextEditor),可以从该上下文中提取数据值和数据项并将其用于着色逻辑.如果不需要上下文,则可以使用通过IValueConverter轻松绑定到DisplayText.

MultiBinding is used to pass a context (XamTextEditor) from which data value and data item can be extracted and used in a coloring logic. If context is not required, simple binding to DisplayText with IValueConverter can be used instead.

更新:

为使XamDataGrid使用您的转换器,您必须像以下XAML代码片段中那样在FieldSettings(而非FieldLayouts)中定义CellValuePresenterStyle:

In order for your converter to be used by XamDataGrid, you must define CellValuePresenterStyle in FieldSettings (not FieldLayouts) like in the following XAML snippet:

<igDP:XamDataGrid Name="DifferenceGrid" DataSource="{Binding Source={StaticResource viewModelLocator}, Path=ViewModel.Model}" 
                      ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Visible">
    <igDP:XamDataGrid.FieldSettings>
        <igDP:FieldSettings CellValuePresenterStyle="{StaticResource cellTemplate}"/>
    </igDP:XamDataGrid.FieldSettings>
</igDP:XamDataGrid>

使用此代码段,您可以为XamDataGrid中的所有单元格指定默认的CellValuePresenterStyle.

With this code snippet, you specify default CellValuePresenterStyle for all cells in a XamDataGrid.

如果要指定CustomClass列使用XamTextEditor,而所有其他列都使用其自己的默认编辑器,则可以通过处理

If you want to specify that your CustomClass column uses XamTextEditor and that all other columns use their own default editor, you can do it by handling FieldLayoutInitialized event like in the following code:

private void OnFieldLayoutInitialized(object sender, FieldLayoutInitializedEventArgs e)
{
    foreach (var field in e.FieldLayout.Fields)
        if (field.DataType == typeof(Model.CustomClass))
        {
            field.Settings.EditorType = typeof(XamTextEditor);
            // Set Editor style in which display converter and edit converter are specified.
            field.Settings.EditorStyle = (Style)((FrameworkElement)sender).FindResource("CustomClassXamTextEditorStyle");
        }
}

上面的

MainWindow.xaml已更新,以反映这些更改.

MainWindow.xaml from above is updated to reflect these changes.

这也是CustomClassToStringConverter的代码,我用来在XamDataGrid中显示和编辑CustomClass时将CustomClass转换为字符串并再次返回(我将Text属性添加到CustomClass,因为我不知道如何从中提取文本):

Here is also code for CustomClassToStringConverter which I used to convert CustomClass to string and back again when displaying and editing CustomClass in XamDataGrid (I added Text property to CustomClass since I didn't know how you extract text from it):

class CustomClassToStringConverter : IValueConverter
{
    public static CustomClassToStringConverter Instance = new CustomClassToStringConverter();

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((CustomClass)value).Text;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new CustomClass() { Text = (string)value };
    }
}

这篇关于无法将cellValuePresenter/TypeConverter应用于XamDataGrid单元的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆