Проблемы с привязкой к содержимому WPF DataGridCell в XAML

Я использовал следующий пост, чтобы реализовать сетку данных, привязанную к списку динамических объектов.

Привязать DynamicObject к DataGrid с автоматическим созданием столбцов?

Метод GetItemProperties ITypedList работает нормально, отображается сетка со всеми описанными мною столбцами.

Я использую настраиваемый дескриптор PropertyDescriptor и переопределяю методы GetValue и SetValue, как описано в приведенном выше сообщении, я также реализую методы TryGetMember и TrySetMember в динамических объектах.

так что в основном у меня есть ComplexObject: DynamicCobject с полем Dictionary и ComplexObjectCollection, реализующим ITypedList и IList.

Все это работает нормально, за исключением случаев, когда я привязываю itemsSource DataGrid к коллекции, в ячейках будет отображаться имя типа SimpleObject, и я действительно хочу реализовать шаблон для отображения значения свойства SimpleObject в текстовом блоке.

Я использовал всевозможные методы, чтобы попытаться получить базовый 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>

Любые предложения будут высоко ценится.

Спасибо

Киран


person Kezza    schedule 13.09.2012    source источник


Ответы (1)


Итак, я нашел решение - поработать над кодом.

В событии AutoGeneratingColumn создайте DataTemplate с элементом управления содержимым и настраиваемым селектором шаблонов (я создал селектор в Xaml и нашел его как ресурс).

Создайте привязку для ContentProperty ContentControl с e.PropertyName в качестве пути

Создайте новый 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, но тогда я сделал это именно так. Также я не тестировал это на динамическом классе, но уверен, что он должен работать в любом случае.

person Kezza    schedule 20.09.2012
comment
привет @Kezza, не могли бы вы поделиться кодом здесь, пожалуйста? Я столкнулся с аналогичной проблемой. Я пытаюсь найти способ установить редактируемую ячейку (isReadOnly) на уровне ячейки с привязкой в ​​xaml. Значением для ячейки является объект, имеющий значение свойства и isEditable. - person stenly; 30.09.2014