2

Infragisticsでも質問しましたが、コードのフォーマット方法がわからないため、ここでは適切にフォーマットされています。

私の目標は、複数の色を使用して各セルのテキストを含む構造化データの表を提示することです。カスタムクラスに保存されているデータを、さまざまな色の複数のテキスト要素を含むラベルまたはテキストブロックに変換するタイプコンバーターがあります。データはデータテーブルで提供され(機能する方法であれば問題ありません)、各値がセルに正しく適用されます。

問題は、TypeConverterを使用する代わりに、ToStringメソッドを使用することです。これをオーバーライドすると、モデルの正しいモデルデータがセルごとにグリッドにマッピングされることがわかります。また、私が使用しているControlTemplateプロパティは適用されません。これは、ControlTemplateが使用されていないことを示しています。

懸念されるのは、データグリッド内で異なる文字の色が異なるテキストを含めることができない場合があることです。もしそうなら、優れたユーザーエクスペリエンスを維持し、デザインをxamlファイル(グリッドでは難しい)に保持しながら実行できる別の方法はありますか。

私のコードはカスタムCellValuePresenterを定義する必要があることを理解しているので、誰かがそれを適用するのを手伝ってくれませんか?

関連するコードをここに投稿しています。そのほとんどは難読化されているため、スペルミスに焦点を当てないでください。

  <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.
    }
  }
4

2 に答える 2

4

XamDataGridセルにはエディターが含まれており、テキストとして表示する必要がある値の場合、エディターはXamTextEditorです。

XamTextEditorのテンプレートを変更し、次のコードのように独自のテンプレートを提供する必要があります。

<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コンテンツを必須に生成するために使用されます。

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セルが仮想化され、セルの仮想化が開始されたとき(CellValuePresenterが別の値を提示するために再利用されるとき)にContentPresenterコンテンツを再生成するようにXamDataGridに指示するためです。また、データバインディングのため、XamDataGridの外部で変更された場合でもコンテンツは再生成されます。

MultiBindingは、データ値とデータ項目を抽出してカラーリングロジックで使用できるコンテキスト(XamTextEditor)を渡すために使用されます。コンテキストが不要な場合は、代わりにIValueConverterを使用したDisplayTextへの単純なバインディングを使用できます。


アップデート:

コンバーターをXamDataGridで使用するには、次のXAMLスニペットのようにFieldSettings(FieldLayoutsではなく)でCellValuePresenterStyleを定義する必要があります。

<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を指定します。

CustomClass列がXamTextEditorを使用し、他のすべての列が独自のデフォルトエディターを使用するように指定する場合は、次のコードのようにFieldLayoutInitializedイベントを処理することで実行できます。

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は、これらの変更を反映するように更新されています。

XamDataGridでCustomClassを表示および編集するときに、CustomClassを文字列に変換して元に戻すために使用したCustomClassToStringConverterのコードもあります(CustomClassからテキストを抽出する方法がわからなかったため、CustomClassにTextプロパティを追加しました)。

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 };
    }
}
于 2012-12-10T21:22:54.967 に答える
0

おかげで私は今それを動かしました。別のデータソースにテキストブロックを提供する必要がありましたが、今はマルチバインディングは必要ありません。しかし、MVVMがまだ適用されるかどうかはわかりませんが、かなり醜い解決策です。

    public DataTable TextBlocks
    {
        get
        {
            Converter converter = new DifferenceToTextConverter();
            DataTable table = new DataTable();

            foreach (DataColumn col in this.Model.Columns)
                table.Columns.Add(col.ColumnName, typeof(TextBlock));

            foreach (DataRow row in this.Model.Rows)
            {
                DataRow addedRow = table.NewRow();
                for (int col = 0; col < row.ItemArray.Length; col++)
                {
                    addedRow[col] = converter.ConvertTo(row[col]);
                }

                table.Rows.Add(addedRow);
            }

            return table;
        }
    }
于 2012-12-14T12:19:54.647 に答える