Die meiste Zeit haben wir Probleme mit ItemChange oder SelectionChanged für Baum, nach viel Mühe fand ich eine funktionierende Lösung für mich. Im Folgenden finden Sie die AntwortSo behandeln Sie ItemChanged-Ereignis für Strukturansicht WPF MVVM
0
A
Antwort
0
Mit unten angefügten Eigenschaft Wenn jemals Baum Element ausgewählt ist oder die Auswahl geändert direkt den Befehl auf das Objekt wirft
public class ControlBehaviour
{
private static IDictionary<object, ICommand> dataContextCommandMap = new Dictionary<object, ICommand>();
private static IDictionary<FrameworkElement, object> elementDataConextMap = new Dictionary<FrameworkElement, object>();
/// <summary>
///
/// </summary>
public static readonly DependencyProperty ControlEventProperty =
DependencyProperty.RegisterAttached("ControlEvent", typeof(RoutedEvent), typeof(ControlBehaviour),
new PropertyMetadata(OnTreeviewSelectionChanged));
/// <summary>
///
/// </summary>
/// <param name="target"></param>
/// <param name="value"></param>
public static void SetControlEvent(DependencyObject target, object value)
{
target.SetValue(ControlEventProperty, value);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <returns></returns>
public static RoutedEvent GetControlEvent(DependencyObject sender)
{
return sender.GetValue(ControlEventProperty) as RoutedEvent;
}
/// <summary>
/// Command to be executed
/// </summary>
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand),
typeof(ControlBehaviour), new PropertyMetadata(CommandChanged));
/// <summary>
/// Set ICommand to the dependency object
/// </summary>
/// <param name="target">dependency object</param>
/// <param name="value">I command</param>
public static void SetCommand(DependencyObject target, object value)
{
target.SetValue(CommandProperty, value);
}
/// <summary>
/// Get ICommand to the dependency object
/// </summary>
/// <param name="sender">dependency object</param>
/// <returns>ICommand of the dependency object</returns>
public static ICommand GetCommand(DependencyObject sender)
{
return sender.GetValue(CommandProperty) as ICommand;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnTreeviewSelectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (sender != null)
{
TreeView element = sender as TreeView;
if (element != null)
{
if (e.NewValue != null)
{
element.SelectedItemChanged += Handler;
}
if (e.OldValue != null)
{
element.SelectedItemChanged -= Handler;
}
}
}
}
/// <summary>
/// ICommand Changed
/// </summary>
/// <param name="sender">dependency object</param>
/// <param name="e">dependency args</param>
private static void CommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (sender != null)
{
FrameworkElement cntrl = sender as FrameworkElement;
if (cntrl != null && cntrl.DataContext != null)
{
if (e.NewValue != null)
{
ICommand cmd = e.NewValue as ICommand;
if (cmd != null)
{
elementDataConextMap[cntrl] = cntrl.DataContext;
dataContextCommandMap[cntrl.DataContext] = cmd;
}
}
cntrl.Unloaded += FrameworkElementUnloaded;
}
}
}
/// <summary>
/// Framework element unload, Clears the removes the ICommand
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void FrameworkElementUnloaded(object sender, RoutedEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element != null && elementDataConextMap.ContainsKey(element))
{
dataContextCommandMap.Remove(elementDataConextMap[element]);
elementDataConextMap.Remove(element);
}
}
/// <summary>
/// Routed Event Handler
/// </summary>
/// <param name="sender">sender</param>
/// <param name="e">EventArgs</param>
static void Handler(object sender, EventArgs e)
{
TreeView treeView = sender as TreeView;
if (treeView != null && treeView.SelectedItem != null && dataContextCommandMap.ContainsKey(treeView.SelectedItem)
&& dataContextCommandMap[treeView.SelectedItem].CanExecute(treeView.SelectedItem))
{
dataContextCommandMap[treeView.SelectedItem].Execute(treeView.SelectedItem);
}
}
}
Unten ist die xMAL die die oben angebaute Eigenschaft verwendet
<TreeView Grid.Row="1" Background="Transparent" ItemsSource="{Binding Directories}" Margin="0,10,0,0" Name="FolderListTreeView"
Height="Auto" HorizontalAlignment="Stretch" Width="300" local:ControlBehaviour.ControlEvent="TreeView.SelectedItemChanged" >
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:FileSystem}" ItemsSource="{Binding SubDirectories}">
<Label Content="{Binding Path= Name}" Name="NodeLabel" local:ControlBehaviour.Command="{Binding OnSelect}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
im Folgenden finden Sie Filesystem-Klasse, die in XAML gebunden ist
/// <summary>
/// Implementation of file system class
/// </summary>
public class FileSystem :BindableBase, IFileSystem, IEnumerable //BindableBase is base class which implemets INotifyPropertyChanged
{
#region Private members
private ObservableCollection<IFileSystem> subDirectoriesField;
private ObservableCollection<IFileSystem> filesField;
#endregion
#region Public properties
/// <summary>
/// Gets and sets all the Files in the current folder
/// </summary>
public ObservableCollection<IFileSystem> SubDirectories
{
get
{
return subDirectoriesField;
}
set
{
if (subDirectoriesField != value)
{
subDirectoriesField = value;
NotifyPropertyChanged("SubDirectories");
}
}
}
/// <summary>
/// Gets and sets all the files in the current folder
/// </summary>
public ObservableCollection<IFileSystem> Files
{
get
{
return filesField;
}
set
{
if (filesField != value)
{
filesField = value;
RaisePropertyChanged("Files");
}
}
}
/// <summary>
/// Gets or sets the type of the file
/// </summary>
public FileSystemType FileType
{
get;
set;
}
/// <summary>
/// Gets or sets the size of the file
/// </summary>
public long Size
{
get;
set;
}
/// <summary>
/// Gets or sets name of the file system
/// </summary>
public string Name
{
get;
set;
}
/// <summary>
/// Gets or sets full path of the file system
/// </summary>
public string FullPath
{
get;
set;
}
/// <summary>
/// object of parent, null if the current node is root
/// </summary>
public FileSystem Parent
{
get;
set;
}
/// <summary>
/// Returns ICommand
/// </summary>
public ICommand OnSelect
{
get
{
return new Command_R(Execute);//Command_R is implemention of your ICommand
}
}
#endregion
#region Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="path">path of the folder</param>
/// <param name="parent">object of the parent</param>
public FileSystem(string fullPath, FileSystem parent, FileSystemType
type = FileSystemType.Directory)
{
Name = fullPath != null ? GetNameFileName(fullPath) : fullPath;
FullPath = fullPath;
Parent = parent;
FileType = type;
FilesAndSubDirectoriesDetails(fullPath);
}
#endregion
#region Public methods
/// <summary>
/// Updates the file size if there is a change
/// </summary>
/// <param name="deleteFilzeSize"></param>
public void UpdateFileSize(long deleteFilzeSize)
{
UpdatePredecessor(this, deleteFilzeSize);
}
/// <summary>
/// Gets the enumeration list
/// </summary>
/// <returns>returns the enumeration list</returns>
public IEnumerator GetEnumerator()
{
return SubDirectories.GetEnumerator();
}
#endregion
#region Private methods
/// <summary>
/// Finds the details of the files and sub directories
/// </summary>
/// <param name="fullPath"></param>
private void FilesAndSubDirectoriesDetails(string fullPath)
{
if (FileType.Equals(FileSystemType.Directory))
{
AddFilesAndSubDirectories(fullPath);
CalculateDirectorySize();
}
else
{
//Write code to calcuate the File Size
//Size = FileInfo.GetSize(fullPath);
}
}
/// <summary>
/// Finds and adds the files and sub directories
/// </summary>
/// <param name="fullPath"></param>
private void AddFilesAndSubDirectories(string fullPath)
{
string[] subDirectories = Directory.GetDirectories(fullPath);
SubDirectories = new ObservableCollection<IFileSystem>();
foreach (string directory in subDirectories)
{
SubDirectories.Add(new FileSystem(directory, this));
}
Files = new ObservableCollection<IFileSystem>();
string[] files = File.GetFiles(fullPath);
foreach (string fileName in files)
{
Files.Add(new FileSystem(fileName, this, FileSystemType.File));
}
}
/// <summary>
/// Calculates the current directory size
/// </summary>
private void CalculateDirectorySize()
{
foreach (FileSystem directory in SubDirectories)
{
Size += directory.Size;
}
foreach (FileSystem file in Files)
{
Size += file.Size;
}
}
/// <summary>
/// Updates the file size of the predecessors
/// </summary>
/// <param name="currentNode">current node</param>
/// <param name="deleteFilzeSize">file to be updated</param>
private void UpdatePredecessor(FileSystem currentNode, long deletedFilzeSize)
{
if (currentNode != null)
{
currentNode.Size -= deletedFilzeSize;
UpdatePredecessor(currentNode.Parent, deletedFilzeSize);
}
}
/// <summary>
/// Executes ICommand
/// </summary>
/// <param name="parameter">parameter</param>
private void Execute(object parameter)
{
//Do your Job
MessageBox.Show(FullPath);
}
#endregion
}
Und die Schnittstelle für die Klasse
/// <summary>
/// Type of the file
/// </summary>
public enum FileSystemType
{
/// <summary>
/// File
/// </summary>
File,
/// <summary>
/// Directory
/// </summary>
Directory
}
/// <summary>
/// Interface for File system
/// </summary>
public interface IFileSystem
{
/// <summary>
/// Gets or sets file type
/// </summary>
FileSystemType FileType
{
get;
set;
}
/// <summary>
/// Gets or sets the file size
/// </summary>
long Size
{
get;
set;
}
/// <summary>
/// Gets or sets name of the file system
/// </summary>
string Name
{
get;
set;
}
/// <summary>
/// Gets or sets full path of the file system
/// </summary>
string FullPath
{
get;
set;
}
}
Verwandte Themen
- 1. Wie MVVM mit der WPF-Strukturansicht implementieren?
- 2. Spaltenüberschrift für eine WPF-Strukturansicht
- 3. Anzeigen eines XDocuments als WPF-Strukturansicht mithilfe eines MVVM ViewModel
- 4. So zeigen Sie Dialoge mit MVVM Light für WPF?
- 5. Get FullPath in WPF-Strukturansicht?
- 6. ScrollIntoView für WPF DataGrid (MVVM)
- 7. Gruppieren von untergeordneten Objekten in WPF-Strukturansicht
- 8. WPF-Strukturansicht mit Spalten mit fester Breite
- 9. Gruppieren von Daten in WPF-Strukturansicht
- 10. MVVM Toolkit (Vorlagen) und XAML Powertoys für wpf mvvm Arbeit?
- 11. So blenden Sie das Stack-Bedienfeld in wpf ein mvvm
- 12. So behandeln Sie Ausnahmen für mehrere Route
- 13. WPF MVVM, ICommand und Repositories
- 14. Refactoring WPF MVVM für erhöhte Testbarkeit
- 15. WPF Globale Klasse MVVM
- 16. WPF MVVM: Konvention über Konfiguration für ResourceDictionary?
- 17. WPF-Strukturansicht: Wo ist die ExpandAll() -Methode
- 18. WPF MVVM TextBox Textbindung
- 19. WPF Caliburn.Micro/mvvm Navigation
- 20. Wpf UserControl und MVVM
- 21. MVVM WPF - Login Logik
- 22. Verwechslung mit WPF MVVM
- 23. CollectionViewSource MVVM-Implementierung für WPF DataGrid
- 24. DependencyProperty Analog für WPF MVVM Modell
- 25. MVVM Treeview wpf (Bindung?)
- 26. WPF ICommand MVVM Implementierung
- 27. WPF MVVM Muster
- 28. WPF MVVM-Dialogbeispiel
- 29. MVVM, WPF und Validierung
- 30. WPF MVVM PasswordBox-Bindung