我正在尝试从TreeView中获取所选项目,但遇到了一些问题。 我正在关注MVVM archetecture。我的ViewModel包含我的模型中的类的集合。所以我已经将TreeView的ItemSource绑定到该集合。我想将TreeView的selectedItem绑定到绑定集合的项目。我怎么做。这是SelectedItem和IsSelected属性的代码。
private static sourceData _selectedItem = null;
/// <summary>
/// Selected Item in the tree
/// </summary>
public static sourceData SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem != value)
{
_selectedItem = value;
}
}
}
private bool _isSelected;
/// <summary>
/// Get/Set for Selected node
/// </summary>
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
_isSelected = value;
if (_isSelected)
{
SelectedItem = this;
OnPropertyChanged("IsSelected");
}
}
}
}
/// <summary>
/// Property changed event
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Property changed event handler
/// </summary>
/// <param name="propertyName"></param>
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
当我调试它时,int SelectedItem = this;
'this'指针包含我的树视图绑定到的集合。我需要一个SelectedDataSource,以便我可以将它分配给选定的Item。如何让我的TreeView返回集合中的selectedItem?
FYi,这是我对TreeView的XAML代码
<TreeView Margin="5,0,0,0" ItemsSource="{Binding SourceData}" Width="390">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding DataContext.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Name="contextMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" >
<MenuItem Name="menuItem" Header="Rename" Command="{Binding RenameCommand}" />
</ContextMenu>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
P.S:如果我在我的模型中编写上面的代码,我会让一切都运行得很好。但是我不能在Model中使用上面的代码,它必须在VM中。
任何帮助将不胜感激。
谢谢
答案 0 :(得分:0)
除了对您的问题的评论之外,WPF TreeView还为MVVM开发人员提出了一些独特的挑战,其中包括检测当前选定的项目。为此,您可以使用附加行为。首先,编写一个静态类来包含行为......
public static class TvBehaviour
{
#region TvSelectedItemChangedBehaviour (Attached DependencyProperty)
public static readonly DependencyProperty TvSelectedItemChangedBehaviourProperty =
DependencyProperty.RegisterAttached("TvSelectedItemChangedBehaviour",
typeof (ICommand),
typeof (TvBehaviour),
new PropertyMetadata(
OnTvSelectedItemChangedBehaviourChanged));
public static void SetTvSelectedItemChangedBehaviour(DependencyObject o, ICommand value)
{
o.SetValue(TvSelectedItemChangedBehaviourProperty, value);
}
public static ICommand GetTvSelectedItemChangedBehaviour(DependencyObject o)
{
return (ICommand) o.GetValue(TvSelectedItemChangedBehaviourProperty);
}
private static void OnTvSelectedItemChangedBehaviourChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
TreeView tv = d as TreeView;
if (tv != null)
{
tv.SelectedItemChanged += (s, a) =>
{
GetTvSelectedItemChangedBehaviour(tv).Execute(a.NewValue);
a.Handled = true;
};
}
}
#endregion
}
然后将类的命名空间导入Xaml(使用xmlns)。然后,您可以沿着这些行声明TreeView ......
<TreeView ItemsSource="{Binding MyList}"
ItemTemplate="{StaticResource My_data_template}"
tvBinding:TvBehaviour.TvSelectedItemChangedBehaviour="{Binding
SelectedItemCommand}"
SelectedValuePath="Name"
>
</TreeView>
将电视行为“连接”到VM中的ICommand。最后,在你的VM中声明ICommand ......
public ICommand SelectedItemCommand {get;组; }
并初始化它......
SelectedItemCommand = new RelayCommand(ExecuteSelectedItemCommand,
CanExecuteSelectedItemCommand);
然后实施你的代表......
private void ExecuteSelectedItemCommand(object obj)
{
// downcast 'obj' to get the instance of the selected item
}
private bool CanExecuteSelectedItemCommand(object obj)
{
return true;
}
当用户选择一个电视项目时,你的“执行”代表将获得该项目的盒装实例,你可以将其拆箱等等。
请注意,此示例中的附加行为假定电视的生命周期与应用程序相同,否则您必须取消附加的行为。它还假设TV ItemsSource绑定了一些合理的东西。
这将解决在保持MVVM兼容的同时获取TV SelectedItem的问题(如果存在MVVM兼容的事情)。
我使用的Relay Command类来自MSDN中的链接文章。出于参考目的,这里是......
public class RelayCommand : ICommand
{ //http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
}
使用上面的MSDN链接获取有关此课程的更多信息。