تحديث ملزمة TreeViewItem باستخدام الرمز؟ (XAML / WPF)
-
13-09-2019 - |
سؤال
انا املك TreeView
ملك من ItemsSource
تم ضبطه على نموذج لدي. 3 مستويات عميقة هي كائن يمكن أن تتغير حالته، بدلا من كتابة وجهة نظر و ViewModel لكل مرحلة (أعمال طويلة جدا)، أردت فقط تحديث هذا التعليمات البرمجية.
لذلك في الأساس لدي حدث يتم إطلاقه بمجرد تحديثات نموذجي، أمسكه بعد ذلك TreeViewItem
المرتبطة بهذا القليل من البيانات. مشكلتي الآن ليس لدي أي فكرة عن كيفية تحديث الربط عليه لتعكس القيمة الجديدة!
هل أستطيع مساعدتك؟
أعلم أن هذه ليست أفضل ممارسة ولكني لا أريد حقا أن أضيع الوقت لكتابة كمية هائلة من التعليمات البرمجية لتحديث شيء واحد فقط.
شكرا كريس
المحلول
يعمل هذا المثال، على الرغم من أن مستوياتهما فقط (وليس 3) عميق. إنه يظهر شاشة تاركوية هرمية بسيطة من المستوى 2 مع البنود الأصل A، B، و C، مع أطفال مرقمة (A.1، B.1، إلخ). عند النقر فوق زر إعادة تسمية B..1، فإنه يتأمل B.1 إلى "Sylvia".
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace UpdateVanillaBindingValue
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private DataClass _data;
public Window1()
{
InitializeComponent();
var data = CreateData();
DataContext = _data = data;
}
private DataClass CreateData()
{
return new DataClass
{
Parents=new List<Parent>
{
new Parent{Name="A",Children=new List<Child>{new Child{Name="A.0"},new Child{Name="A.1"}}},
new Parent{Name="B",Children=new List<Child>{new Child{Name="B.0"},new Child{Name="B.1"},new Child{Name="B.2"}}},
new Parent{Name="C",Children=new List<Child>{new Child{Name="C.0"},new Child{Name="C.1"}}}
}
};
}
private void Rename_Click(object sender, RoutedEventArgs e)
{
var parentB = _data.Parents[1];
var parentBItem = TheTree.ItemContainerGenerator.ContainerFromItem(parentB) as TreeViewItem;
parentB.Children[1].Name = "Sylvia";
var parentBItemsSource = parentBItem.ItemsSource;
parentBItem.ItemsSource = null;
parentBItem.ItemsSource = parentBItemsSource;
}
}
public class DataClass
{
public List<Parent> Parents { get; set; }
}
public class Parent
{
public string Name { get; set; }
public List<Child> Children { get; set; }
}
public class Child
{
public string Name { get; set; }
}
}
<Window x:Class="UpdateVanillaBindingValue.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.Resources>
<DataTemplate x:Key="ChildTemplate">
<TextBlock Margin="50,0,0,0" Text="{Binding Name}" />
</DataTemplate>
<HierarchicalDataTemplate x:Key="ParentTemplate" ItemsSource="{Binding Children}" ItemTemplate="{StaticResource ChildTemplate}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</Grid.Resources>
<TreeView x:Name="TheTree" ItemsSource="{Binding Parents}" ItemTemplate="{StaticResource ParentTemplate}" />
<Button VerticalAlignment="Bottom" HorizontalAlignment="Center" Content="Rename B.1" Click="Rename_Click" />
</Grid>
</Window>
هذا هو الاختراق، ولكنه يعيد تقييم DataTemplate في كل مرة يتم فيها تغييرات خصائص OctionSource.
من الناحية المثالية، ستنفذ InotifyPropertychanged على فئة كائن النموذج الخاص بك أن هذا TreeViewItem مرتبط به، ولديه إطلاق الحدث الخاص بالخصوصية عند تغيير القيمة. في الواقع، يجب أن تكون حريصا على عدم تكبد تسرب الذاكرة لأنه لا: العثور على تسرب الذاكرة في تطبيقات WPF.
نصائح أخرى
هل أنت متأكد من أنه لن يكون من الأسهل تنفيذ inotifypropertychanged على الفئة ذات الصلة؟
يبدو وكأنك قد تحتاج إلى إلقاء نظرة على UpdateSource
و UpdateTarget
أساليب.
على الرغم من أنني لست متأكدا تماما، سيعمل ذلك عندما تكون في الواقع ملزمة TreeView ItemSource
إلى بنية بيانات هرمية، ولكن من حيث سأبدأ التحقيق.