2

Object データバインディングを使用して WPF TreeView を作成する際に深刻な問題が発生しています。

アプリケーションは、構成ファイル エディターです。正しい XML 形式にシリアル化できる Object 構造を定義しました。

私が抱えている問題は、正しい階層を示す TreeView でオブジェクト インスタンスをフォーマットすることです。TreeView は Channel ノードのみをレンダリングし、他には何もレンダリングしません。

public class Objects
{
    public List<Channel> Channels { get; set; }
}

public class Channel 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public Reader Reader { get; set; }
    public Filters Filters { get; set; }
    public Router Router { get; set; }
    public Persister Persister { get; set; }
}

public class Filters : ArrayList
{
    public string StopOnFailure { get; set; }
}

public class Reader
{
    public string Id { get; set; }
    public string Name { get; set; }
}

のすべての子クラスにはChannel、プロパティIdとが含まれていますName。Filters クラスは、同じプロパティ定義を持つ他の型のコレクションです。

ここにXAMLがあります

 <Window.Resources>
    <ObjectDataProvider x:Key="data"/>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Channel}">
        <WrapPanel>
            <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
            <TextBlock Text=" [" />
            <TextBlock  Text="{Binding Path=Id}" />
            <TextBlock Text="]" />
        </WrapPanel>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <TreeView Margin="12,12,12,96" Name="treeView1" ItemsSource="{Binding Source={StaticResource data}, Path=Channels}">
    </TreeView>
</Grid>

データ インスタンスを作成するコード ビハインド

Objects config;
var serializer = new XmlSerializer(typeof(Objects));
using (var stream = new FileStream(@"C:\test.xml", FileMode.Open))
{
    config = (Objects)serializer.Deserialize(stream);
}

var dp = (ObjectDataProvider)FindResource("data");
dp.ObjectInstance = config;

数え切れないほどの例を見てきましたが、何が間違っているのかまだわかりません。助けてくれてありがとう。

アップデート:

<HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Objects}" ItemsSource="{Binding Path=Channels}"/>
<HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Channel}" ItemsSource="Binding Path=Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

<DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>

に変更はありませんTreeView。この変更により、私はまだChannelリストされているだけで、他には何もありません。

4

4 に答える 4

2

TreeViewの画像にオブジェクトが表示されることはないため、このテンプレートは必要ないと思います。

<HierarchicalDataTemplate
    DataType="{x:Type ConfigurationEditor:Objects}" 
    ItemsSource="{Binding Path=Channels}"/>

これをXAMLで設定しました。これは、チャネルを表示します。完璧です。

<TreeView 
    Margin="12,12,12,96" Name="treeView1" 
    ItemsSource="{Binding Source={StaticResource data}, Path=Channels}">
</TreeView>

ここで、リーダーも表示する必要があります。ただし、ItemsSourceとしてIEnumerableタイプのオブジェクトしか指定できないため、ItemsSourceとして「Reader」を指定する以下のテンプレートは正しくありません。

<HierarchicalDataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" 
    ItemsSource="{Binding Path=Reader}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

したがって、リーダー名も表示する場合は、以下に示すテンプレートを使用してください。

<DataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" >
    <StackPanel>
        <TextBlock Text="{Binding Path=Name}"/>
        <TextBlock Text="{Binding Path=Reader.Name}"/>
    <StackPanel>
</DataTemplate>
于 2009-09-13T07:53:03.337 に答える
2

@Gimalayの答えを拡張すると、問題は、TreeView子ノードのデータをどこで取得するかわからないことです。ではなくTreeViewを使用してに通知します。HierarchialDataTemplateDataTemplate

<HierarchialDataTemplate DataType="{x:Type ConfigurationEditor:Channel}"
    ItemsSource="...">
    <WrapPanel>
        <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
        <TextBlock Text=" [" />
        <TextBlock  Text="{Binding Path=Id}" />
        <TextBlock Text="]" />
    </WrapPanel>
</HierarchialDataTemplate>

両者の主な違いはItemsSource属性です。これは、子ノードとして使用するオブジェクトのコレクションを返すバインディング式です。

問題は、子を取得するプロパティが 1 つだけではなく、いくつかあることです。それらをすべて 1 つのプロパティに結合するか、すべての子ノードを返す別のプロパティを追加する必要があります。

最後に、DataTemplate各子アイテム タイプに対してを定義して、TreeViewがそれらを表示する方法を認識できるようにする必要があります (HierarchialDataTemplate子ノードがある場合は、子にも を使用できます)。

于 2009-09-13T01:57:10.810 に答える
0

そのためだけに、階層データテンプレートは、アイテムソースが実際にそれ自体の中に階層を持っている場合に使用されます。つまり、オブジェクト自体にはいくつかの階層があり、親オブジェクトは子オブジェクトのリストを保持します。

例として、各チャネルが以下のようなプロパティサブチャネルを持っている場合があります。

public class Channel 
{
    public string Id { get; set; }
    public string Name { get; set; }
    public ObservableCollection<Channel> SubChannels { get; }
}

次に、このようなテンプレートを使用できます。

<HierarchicalDataTemplate 
    DataType="{x:Type ConfigurationEditor:Channel}" 
    ItemsSource="{Binding Path=SubChannels}">
    <TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>

これで、オブジェクト構造をマルチレベルの深さにすることができ、各サブチャネルにもサブチャネルがあります。

また、この例では、同じタイプのChannelを使用して、サブチャネルの階層を作成したことに注意してください。別のタイプを使用することもできます。たとえば、各チャネルにリーダーのリストがあります。

于 2009-09-13T08:16:51.860 に答える
0

さて、試行錯誤の末、思い通りに動作させることができました。これが私がやった方法です。

オブジェクトに、ChannelTreeView に表示したい他のすべてのプロパティのコレクションである新しいプロパティを追加しました

public ArrayList Components
{
    get { return new ArrayList { Reader, Filters, Router, Persister  }; } 
    set
    {
        ArrayList list = value;
        if (list != null)
        {
            foreach (var item in list)
            {
                if (item is Reader)
                {
                    Reader = (Reader)item;
                }
                else if (item is Router)
                {
                    Router = (Router) item;
                }
                else if (item is Persister)
                {
                    Persister = (Persister) item;
                }
                else if (item is Filters)
                {
                    Filters = (Filters) item;
                }
            }
        }
    }
}

次に、ツリービューを表示するための XAML は次のとおりです。

    <HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Channel}" ItemsSource="{Binding Path=Components}">
        <WrapPanel>
            <TextBlock FontWeight="Bold" Text="{Binding Path=Name}" />
            <TextBlock Text=" [" />
            <TextBlock  Text="{Binding Path=Id}" />
            <TextBlock Text="]" />
        </WrapPanel>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type ConfigurationEditor:Filters}" ItemsSource="{Binding Path=.}">
        <TextBlock Text="Filters"/>
        <HierarchicalDataTemplate.ItemTemplate>
            <DataTemplate >
                <TextBlock Text="{Binding Path=Name}"/>
            </DataTemplate>
        </HierarchicalDataTemplate.ItemTemplate>
    </HierarchicalDataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Reader}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Router}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type ConfigurationEditor:Persister}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>

アンディ、私を正しい軌道に乗せてくれてありがとう。

于 2009-09-14T22:29:47.957 に答える