1

次の投稿を使用して、動的オブジェクトのリストにバインドされたデータグリッドを実装しました

自動列生成を使用してDynamicObjectをDataGridにバインドしますか?

ITypedListメソッドのGetItemPropertiesは正常に機能し、説明したすべての列を含むグリッドが表示されます。

上記の投稿で説明されているように、カスタムPropertyDescriptorを使用して、GetValueメソッドとSetValueメソッドをオーバーライドします。また、動的オブジェクトにTryGetMemberメソッドとTrySetMemberメソッドを実装します。

つまり、基本的に、フィールドディクショナリを持つComplexObject:DynamicCobjectと、ITypedListおよびIListを実装するComplexObjectCollectionがあります。

これはすべて正常に機能しますが、DataGridのitemsSourceをコレクションにバインドすると、セルにSimpleObjectタイプ名が表示され、実際にテンプレートを実装して、SimpleObjectのプロパティValueをテキストブロックに表示します。

基礎となるSimpleObjectを取得するためにあらゆる種類のメソッドを使用しましたが、何も機能せず、常に行のComplexObjectを取得します。自動生成された列を使用していますが、これは常にテキスト列を生成するようです。これが問題になる可能性がありますが、セルのプロパティのどこかから基になるSimpleObjectを取得できないのはなぜですか。

以下は私の理想的な解決策ですが、これは機能しません。

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="DefaultNodeTempate">
            <ContentControl Content="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                              Path=Content}">
                <ContentControl.Resources>
                        <DataTemplate DataType="local:SimpleObjectType">
                            <TextBlock Text="{Binding Value}" />
                        </DataTemplate>
                </ContentControl.Resources>
            </ContentControl>
        </DataTemplate>
    </Grid.Resources>
    <DataGrid ItemsSource="{Binding ElementName=mainWin, Path=DynamicObjects}">
        <DataGrid.Resources>
            <Style TargetType="DataGridCell">
                <Setter Property="ContentTemplate" Value="{StaticResource DefaultNodeTempate}" />
            </Style>
        </DataGrid.Resources>
    </DataGrid>
</Grid>

任意の提案をいただければ幸いです。

ありがとう

キエラン

4

1 に答える 1

0

そのため、解決策はコードビハインドでいくつかの作業を行うことであることがわかりました。

AutoGeneratingColumnイベントで、コンテンツコントロールとカスタムテンプレートセレクターを使用してDataTemplateを作成します(Xamlでセレクターを作成し、それをリソースとして見つけました)。

パスとしてe.PropertyNameを使用して、ContentControlのContentPropertyのバインディングを作成します

新しいDataGridTemplateColumnを作成し、新しい列CellTemplateを新しいDataTemplateに設定します

e.Columnを新しい列に置き換え、セルのデータコンテキストをその列の動的プロパティにバインドします。

誰かがこれに何か洗練を持っているならば、あなたの考えを自由に共有してください。

ありがとう

編集:要求に応じて私のソリューションのサンプルコード

カスタムテンプレートセレクター:

public class CustomDataTemplateSelector : DataTemplateSelector
{
    public List<DataTemplate> Templates { get; set; }

    public CustomDataTemplateSelector()
        : base()
    {
        this.Templates = new List<DataTemplate>();
    }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        DataTemplate template = null;
        if (item != null)
        {
            template = this.Templates.FirstOrDefault(t => t.DataType is Type ? (t.DataType as Type) == item.GetType() : t.DataType.ToString() == item.GetType().ToString());
        }

        if (template == null)
        {
            template = base.SelectTemplate(item, container);
        }

        return template;
    }
}

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="ParentControl">
        <Grid.Resources>
            <local:CustomDataTemplateSelector x:Key="MyTemplateSelector" >
                <local:CustomDataTemplateSelector.Templates>
                    <DataTemplate DataType="{x:Type local:MyCellObject}" >
                        <TextBox Text="{Binding MyStringValue}" IsReadOnly="{Binding IsReadOnly}" />
                    </DataTemplate>
                </local:CustomDataTemplateSelector.Templates>
            </local:CustomDataTemplateSelector>
        </Grid.Resources>
        <DataGrid ItemsSource="{Binding Rows}" AutoGenerateColumns="True" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" >
        </DataGrid>
    </Grid>
</Window>

背後にあるコード:

private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    // Get template selector
    CustomDataTemplateSelector selector = ParentControl.FindResource("MyTemplateSelector") as CustomDataTemplateSelector;

    // Create wrapping content control
    FrameworkElementFactory view = new FrameworkElementFactory(typeof(ContentControl));

    // set template selector
    view.SetValue(ContentControl.ContentTemplateSelectorProperty, selector);

    // bind to the property name
    view.SetBinding(ContentControl.ContentProperty, new Binding(e.PropertyName));

    // create the datatemplate
    DataTemplate template = new DataTemplate { VisualTree = view };

    // create the new column
    DataGridTemplateColumn newColumn = new DataGridTemplateColumn { CellTemplate = template };

    // set the columns and hey presto we have bound data
    e.Column = newColumn;
}

データテンプレートを作成するためのより良い方法があるかもしれません。最近、MicrosoftがXamlReaderの使用を提案していることを読みましたが、これが当時の私が行った方法です。また、これを動的クラスでテストしたことはありませんが、どちらの方法でも機能するはずです。

于 2012-09-20T10:46:35.127 に答える