בניגוד לWinFroms בה הדרך להציג ויזואל מסויים הוא כתיבת קוד לוגי,
WPF בנויה להפרדה מוחלטת בין הנתונים והקוד (הפרוצדורלי) לבין התצוגה (שבנויה בעיקר בהצהרות XAML).
בWPF לא אמורים לכתוב בקוד צבע וכדומה.
כיון שלא לגמרי הבנתי את הנושא יכול להיות שהקוד שאני מציע לא מתאים לגמרי, תשתמש בו ותשנה אותו לפי הצרכים. קודם כל בניית העץ:
public class EntryItem
{
public string FullName { get; protected set; }
public string Name { get; protected set; }
public bool IsMyBook { get; protected set; }
public bool IsDirectory { get; protected set; }
public bool IsChecked { get; set; }
}
class DirectoryItem : EntryItem
{
private DirectoryItem(string fullName, bool isMyBook)
{
FullName = fullName;
var name = System.IO.Path.GetFileNameWithoutExtension(fullName);
Name = Z_TranslatorClass.TranslateFolderName(name);
IsMyBook = isMyBook;
Entries = new List<EntryItem>();
IsDirectory = true;
}
public List<EntryItem> Entries { get; private set; }
public static DirectoryItem CreateTree(string dirPath, bool isMyBook)
{
var dir = new DirectoryItem(dirPath, isMyBook);
foreach (var element in Directory.GetDirectories(dirPath))
dir.Entries.Add(CreateTree(element, isMyBook));
foreach (var element in Directory.GetFiles(dirPath))
dir.Entries.Add(new FileItem(element, isMyBook));
return dir;
}
}
public class FileItem : EntryItem
{
public FileItem(string fullName, bool isMyBook)
{
FullName = fullName;
Name = System.IO.Path.GetFileNameWithoutExtension(fullName);
if (FullName.Contains("ToratEmetInstall"))
Name = Z_TranslatorClass.TranslateFilename(FullName);
IsMyBook = isMyBook;
}
}
השמת המודל בTreeView:
var root = DirectoryItem.CreateTree(@"D:\Bla\Bla\", true).Entries;
tv.ItemsSource = root;
והתבנית התצוגתית:
<TreeView Name="tv" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="500">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Entries}">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked}" />
<TextBlock Visibility="Collapsed" Name="icon">🗀</TextBlock>
<TextBlock Text="{Binding Name}" Name="text" />
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding IsChecked}" Value="True" >
<Setter TargetName="text" Property="Foreground" Value="Firebrick" />
</DataTrigger>
<DataTrigger Binding="{Binding IsDirectory}" Value="True" >
<Setter TargetName="icon" Property="Visibility" Value="Visible" />
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
כעת בעת לחיצה על הCheckBox הערך של הIsChecked משתנה, ותוכל לאסוף את הנתונים הללו מהמודל ולא צריך לעקוב אחרי מצבו של הפקד.
בגדול, כל העסק בWPF צריך להיות על דרך זו, הפרדה ואיגוד (Binding) בין התצוגה לקוד ולא להיפך - הקוד לא אמור להכיר על הButton וכולי.