Bind WPF Extended Toolkit PropertyGrid to a dictionary or other dynamic source?

StackOverflow https://stackoverflow.com/questions/12213799

  •  29-06-2021
  •  | 
  •  

سؤال

I have an XML file with several child elements. Each child element contains a series of elements, but the XML schema is undocumented, so I cannot possibly account for every possible element name. My goal is to provide an editor view for each child element. For example:

XML File

<root>
    <element>
        <subelement1>value</subelement>
        <randomName88787>value</randomName>
        <somethingTotallyFunky>value</somethingTotallyFunky>
        <iHaveNoIdeaWhatThisWillBe>value</iHaveNoIdeaWhatThisWillBe>
    </element>
</root>

I was hoping to use the WPF Toolkit's PropertyGrid control (or something similar) to present a list of all child elements of <element>, but this control is designed to be bound to a CLR object. Of course I can't define a class with properties because I don't know what those properties will be. I've tried the following code to bind to an expando object:

var expando = new ExpandoObject();
var dict = (IDictionary<string, object>)expando;
foreach (var prop in unit.Elements())
{
    if (dict.ContainsKey(prop.Name.LocalName) == false)
    {
        dict.Add(prop.Name.LocalName, (string)prop.Value);
    }
}

Properties.SelectedObject = expando;

But no properties are displayed. It doesn't seem to handle ExpandoObject very well. Is there a better way to approach what I'm trying to do? A better control to do it with?

هل كانت مفيدة؟

المحلول

Actually, you can do this without using any custom objects. Try this XAML with your example data in a file named data.xml:

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <XmlDataProvider x:Key="data" Source="data.xml" XPath="/root/element/*"/>
</Window.Resources>
<Grid>
    <ListView ItemsSource="{Binding Source={StaticResource data}}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Tag" Width="100">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Label Content="{Binding Path=Name}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Value" Width="100">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox Text="{Binding Path=InnerText}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>
</Window>

I expect you'll find any values that are changed by the user in XmlDataProvider.Document, so saving that should persist the user's changes.

نصائح أخرى

Have a look at this, it should basically explain everything. In short, implementing ICustomTypeDescriptor (on a type derived from ExpandoObject) should work fine; I took a look at the Extended WPF Toolkit source code and I think it will handle it properly.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top