سؤال

لدي مجموعة من قاعدة البيانات الكائنات التي تحتوي على مجموعات من كل المخطط الكائنات المستخدم الكائنات.اريد ربط لهم TreeView ولكن إضافة إضافية ثابتة المستويات في التسلسل الهرمي ، بحيث ينتج عن ذلك TreeView تبدو أكثر أو أقل مثل هذا:

<TreeView>
    <TreeViewItem Header="All the databases:">
        <TreeViewItem Header="Db1">
            <TreeViewItem Header="Here's all the schemas:">
                <TreeViewItem Header="Schema1"/>
                <TreeViewItem Header="Schema2"/>
            </TreeViewItem>
            <TreeViewItem Header="Here's all the users:">
                <TreeViewItem Header="User1"/>
                <TreeViewItem Header="User2"/>
            </TreeViewItem>
        </TreeViewItem>
        <TreeViewItem Header="Db2">
            <TreeViewItem Header="Here's all the schemas:">
                <TreeViewItem Header="Schema1"/>
                <TreeViewItem Header="Schema2"/>
            </TreeViewItem>
            <TreeViewItem Header="Here's all the users:">
                <TreeViewItem Header="User1"/>
                <TreeViewItem Header="User2"/>
            </TreeViewItem>
        </TreeViewItem>
    </TreeViewItem>
</TreeView>

وكنت قادرا على الحصول على قريبة جدا من ما أريد باستخدام القوالب التالية:

<Window.Resources>
    <HierarchicalDataTemplate DataType="{x:Type smo:Database}">
        <TreeViewItem Header="{Binding Path=Name}">
            <TreeViewItem Header="Here's all the schemas:" ItemsSource="{Binding Path=Schemas}"/>
            <TreeViewItem Header="Here's all the users:" ItemsSource="{Binding Path=Users}"/>
        </TreeViewItem>
    </HierarchicalDataTemplate>
    <DataTemplate DataType="{x:Type smo:Schema}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type smo:User}">
        <TextBlock Text="{Binding Path=Name}"/>
    </DataTemplate>
</Window.Resources>

ثم في قانون تعيين ملزمة مثل هذا:

TreeViewItem treeViewItem = new TreeViewItem();
treeViewItem.Header = "All the databases:";
treeViewItem.ItemsSource = server.Databases;
treeView.Items.Add(treeViewItem);

مما أدى TreeView يبدو أنني أريد ذلك ولكن ليس من الممكن تحديد معين المخطط أو المستخدم.على ما يبدو WPF يرى الشجرة الفرعية بالكامل متجذرة في قاعدة البيانات العقدة عنصر واحد, وهو الوحيد الذي يحدد كل شيء.أنا بحاجة إلى أن يكون قادرا على تحديد معين المخطط المستخدم أو البيانات الخاصة بنا.كيف يمكنني تعيين قوالب الارتباطات بحيث يعمل بالطريقة التي أريد ؟

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

المحلول

يا رجل هذا هو محبطة بشكل لا يصدق المهمة.لقد حاولت فعل ذلك بنفسي عدة مرات.لدي مشابهة جدا شرط حيث كنت قد حصلت على شيء مثل فئة العملاء التي لديها كل مواقع مجموعة أوامر المجموعة.أردت مواقع أوامر "المجلدات" في طريقة عرض الشجرة.كما كنت قد اكتشفت كل TreeView الأمثلة التي تظهر لك كيفية ربط الذاتي الرجوع أنواع هي إلى حد كبير غير مجدية.

أولا أنا لجأت إلى بناء يدويا شجرة FolderItemNode و ItemNode الأشياء التي أود أن تولد في ViewModel ولكن هذا هزم الغرض الملزم لأنه لن يستجيب الأساسية جمع التغييرات.

ثم جئت حتى مع النهج الذي يبدو للعمل بشكل جيد جدا.

  • في المذكورة أعلاه نموذج كائن ، أنا خلق فئات LocationCollection و OrderCollection.كلاهما ترث من ObservableCollection و تجاوز ToString() للعودة "المواقع" و "أوامر" على التوالي.
  • لقد خلق MultiCollectionConverter الفئة التي تطبق IMultiValueConverter
  • أنا خلقت FolderNode الفئة التي لها اسم و البنود الملكية.هذا هو العنصر النائب كائن من شأنها أن تمثل "المجلدات" في طريقة عرض الشجرة.
  • تعريف hierarchicaldatatemplate أن استخدام MultiBinding في أي مكان أن كنت تريد أن مجموعة متعددة الطفل مجموعات في مجلدات.

مما أدى XAML يشبه رمز أدناه يمكنك الاستيلاء على الملف المضغوط الذي يحتوي على جميع دروس و XAML في العمل على سبيل المثال.

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Local="clr-namespace:WpfApplication2"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">

    <Window.Resources>

        <!-- THIS IS YOUR FOLDER NODE -->
        <HierarchicalDataTemplate DataType="{x:Type Local:FolderNode}" ItemsSource="{Binding Items}">
            <Label FontWeight="Bold" Content="{Binding Name}" />
        </HierarchicalDataTemplate>

        <!-- THIS CUSTOMER HAS TWO FOLDERS, LOCATIONS AND ORDERS -->
        <HierarchicalDataTemplate DataType="{x:Type Local:Customer}">
            <HierarchicalDataTemplate.ItemsSource>
                <MultiBinding>
                    <MultiBinding.Converter>
                        <Local:MultiCollectionConverter />
                    </MultiBinding.Converter>
                    <Binding Path="Locations" />
                    <Binding Path="Orders" />
                </MultiBinding>
            </HierarchicalDataTemplate.ItemsSource>
            <Label Content="{Binding Name}" />
        </HierarchicalDataTemplate>

        <!-- OPTIONAL, YOU DON'T NEED SPECIFIC DATA TEMPLATES FOR THESE CLASSES -->
        <DataTemplate DataType="{x:Type Local:Location}">
            <Label Content="{Binding Title}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type Local:Order}">
            <Label Content="{Binding Title}" />
        </DataTemplate>

    </Window.Resources>

    <DockPanel>
        <TreeView Name="tree" Width="200" DockPanel.Dock="Left" />
        <Grid />
    </DockPanel>

</Window>

Folders in TreeView

نصائح أخرى

والمشكلة هي أن تريفيف ليس جيدا جدا تناسب ما تريد acomplish: وتتوقع كل subnodes أن تكون من نفس النوع. كما عقدة قاعدة البيانات لديها عقدة من نوع Collection<Schemas> ومن نوع Collection<Users> لا يمكنك استخدام HierarchicalDataTemplate. أفضل نهج هو استخدام موسعات المتداخلة التي تحتوي على مربعات سرد.

ورمز أدناه يفعل ما تريد أعتقد، في حين يجري في أقرب وقت ممكن إلى القصد الأصلي الخاص بك:

<Window x:Class="TreeViewSelection.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:smo="clr-namespace:TreeViewSelection"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <Style TargetType="ListBox">
            <Setter Property="BorderThickness" Value="0"/>
        </Style>
        <DataTemplate DataType="{x:Type smo:Database}">
                <TreeViewItem Header="{Binding Name}">
                    <TreeViewItem Header="Schemas">
                        <ListBox ItemsSource="{Binding Schemas}"/>
                    </TreeViewItem>
                    <TreeViewItem Header="Users">
                    <ListBox ItemsSource="{Binding Users}"/>
                </TreeViewItem>
                </TreeViewItem> 
        </DataTemplate>
        <DataTemplate DataType="{x:Type smo:User}" >
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type smo:Schema}">
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </Window.Resources>
    <StackPanel>
        <TreeViewItem ItemsSource="{Binding DataBases}" Header="All DataBases">
        </TreeViewItem>
    </StackPanel>
</Window>

using System.Collections.ObjectModel;
using System.Windows;

namespace TreeViewSelection
{
    public partial class Window1 : Window
    {
        public ObservableCollection<Database> DataBases { get; set; }
        public Window1()
        {
            InitializeComponent();
            DataBases = new ObservableCollection<Database>
                            {
                                new Database("Db1"),
                                new Database("Db2")
                            };
            DataContext = this;
        }
    }

    public class Database:DependencyObject
    {
        public string Name { get; set; }
        public ObservableCollection<Schema> Schemas { get; set; }
        public ObservableCollection<User> Users { get; set; }

        public Database(string name)
        {
            Name = name;
            Schemas=new ObservableCollection<Schema>
                        {
                            new Schema("Schema1"),
                            new Schema("Schema2")
                        };
            Users=new ObservableCollection<User>
                      {
                          new User("User1"),
                          new User("User2")
                      };
        }
    }

    public class Schema:DependencyObject
    {
        public string Name { get; set; }
        public Schema(string name)
        {
            Name = name;   
        }
    }

    public class User:DependencyObject
    {
        public string Name { get; set; }
        public User(string name)
        {
            Name = name;
        }
    }
}

وتحتاج إلى ملء خصائص كنت تستخدم في الربط مع البيانات من قاعدة البيانات الخاصة بك. حاليا كنت تستخدم TreeViewItem الجديدة، وذلك باستخدام بأنها مصدر البيانات، لذلك ما تقوله حول هذا الموضوع رؤية كل شيء كما عقدة واحدة المنطقي، كما كنت قد وضعت في عقدة واحدة.

وتحتاج إلى تحميل البيانات قاعدة البيانات الخاصة بك وإرفاقه الخصائص التي استخدمتها في قالب WPF البنود الخاصة بك ملزمة كما.

إليك تعديل من حل جوش للعمل مع SMO (بياني مشكلة الأصلي):

<Window.Resources>
    <HierarchicalDataTemplate DataType="{x:Type local:FolderNode}" ItemsSource="{Binding Items}">
        <TextBlock Text="{Binding Name}"/>
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate DataType="{x:Type smo:Database}">
        <HierarchicalDataTemplate.ItemsSource>
            <MultiBinding>
                <MultiBinding.Converter>
                    <local:MultiCollectionConverter />
                </MultiBinding.Converter>
                <Binding Path="Schemas" />
                <Binding Path="Users" />
            </MultiBinding>
        </HierarchicalDataTemplate.ItemsSource>
        <TextBlock Text="{Binding Name}"/>
    </HierarchicalDataTemplate>
    <DataTemplate DataType="{x:Type smo:User}" >
        <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type smo:Schema}">
        <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
</Window.Resources>

ووتحويل تعديل:

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    FolderNode[] result = new FolderNode[values.Length];
    for (int i = 0; i < values.Length; ++i)
    {
        result[i].Items = (IEnumerable)values[i];
        result[i].Name = values[i] is UserCollection ? "Users" : "Schemas";
    }
    return result;
}
<اقتباس فقرة>   

<قوية> نسب ملاحظة: محتوى نسخ من الحل النهائي OP ، ونشر باعتباره < وأ href = "https://stackoverflow.com/revisions/1815056/3"> تحرير على سؤال ، بدلا من أن تكون جوابا

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