TreeView لا عرض التسلسل الهرمي كائن
-
06-07-2019 - |
سؤال
أواجه بعض المتاعب الخطيرة خلق WPF TreeView مع كائن ربط البيانات.
التطبيق هو config محرر.قمت بتعريف كائن الهيكل الذي يمكن أن يكون تسلسل الصحيح تنسيق XML.
المشكلة أواجه هو التنسيق مثيل الكائن في TreeView تبين الصحيح الهرمي.TreeView إلا جعل قناة عقدة و لا شيء آخر.
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
.مرشحات الصف هو مجموعة من الأنواع الأخرى مع نفس الخاصية التعريف.
هنا هو 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
سرد و لا شيء آخر.
المحلول
التوسع في @Gimalay الجواب, المشكلة هي أن TreeView
لا أعرف أين يمكن الحصول على البيانات لأي طفل العقد.يمكنك إبلاغ TreeView
باستخدام HierarchialDataTemplate
, بدلا من DataTemplate
:
<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
السمة.هذا هو ملزم التعبير بإرجاع مجموعة من الكائنات لاستخدام الطفل العقد.
المشكلة هي أن لديك عدد قليل من الخصائص للحصول على الأطفال ، وليس واحدة فقط.تحتاج إما إلى الجمع بين كل منهم في خاصية واحدة ، أو إضافة عقار آخر يعود كل من الطفل العقد.
أخيرا, سوف تحتاج إلى تعريف DataTemplate
لكل طفل نوع البند ، بحيث TreeView
يعرف كيفية عرض لهم (يمكنك استخدام HierarchialDataTemplate
الأطفال كما لو كانوا في تحويل الطفل العقد).
نصائح أخرى
أنا لا أعتقد أنك بحاجة إلى هذا النموذج الأشياء لا تأتي أبدا في الصورة في 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>
الآن تريد للقارئ أن يظهر كذلك. ولكن واحدة فقط يمكن تحديد كائنات من نوع IEnumerable كما ItemsSource, لذا القالب أدناه هو غير الصحيحة التي تنص على "القارئ" كما ItemsSource.
<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>
من أجل ذلك البيانات الهرمية قوالب تستخدم عندما البنود مصدر في الواقع التسلسل الهرمي داخل نفسه.أي أن الكائنات نفسها بعض الهرمي مع الكائنات الأصل حفظ قائمة من الكائنات التابعة.
وعلى سبيل المثال ، قد يكون كل قناة لديها خاصية SubChannels مثل أدناه.
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>
الآن بنية الكائن يمكن أن يكون متعدد المستويات العميقة مع كل subchannel مرة أخرى بعد أن subchannels.
أيضا لاحظ أنه في المثال استخدمت نفس النوع, قناة, على إنشاء التسلسل الهرمي من subchannels.ونحن يمكن أن تستخدم نوع آخر ، ويقول كل قناة وجود قائمة من القراء.
حسنا, بعد الكثير من المحاكمة خطأ كنت قادرا على الحصول على هذا العمل كما أردت.هنا هو كيف فعلت ذلك.
في بلدي Channel
كائن لقد تم إضافة خاصية جديدة أن مجموعة من الخصائص الأخرى التي أردت عرضها في TreeView
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 على النحو التالي لعرض treeview.
<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>
شكرا اندي تضعني على الطريق الصحيح.