C# Treeview已扩展,但未启动
我正在尝试向C# Treeview已扩展,但未启动,c#,wpf,mvvm,treeview,C#,Wpf,Mvvm,Treeview,我正在尝试向TreeView添加捕获IsExpanded事件的功能。因此,当某个项目将展开时,它将在视图模型上引发属性或命令 这是我的密码: 我在viewmodel中还有一个属性用于IsExpanded(以及IsSelected),当我展开TreeviewItem时,这些属性都不会出现。 有什么想法吗 感谢大家,当节点展开且一切正常时,尝试重现问题并实现调用命令的附加行为。解决方案的完整代码: XAML <Window x:Class="TreeViewTest.MainWindow"
TreeView
添加捕获IsExpanded
事件的功能。因此,当某个项目将展开时,它将在视图模型上引发属性或命令
这是我的密码:
我在viewmodel中还有一个属性用于IsExpanded
(以及IsSelected),当我展开TreeviewItem
时,这些属性都不会出现。
有什么想法吗
感谢大家,当节点展开且一切正常时,尝试重现问题并实现调用命令的附加行为。解决方案的完整代码: XAML
<Window x:Class="TreeViewTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sotc="clr-namespace:TreeViewTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<sotc:MainWindowViewModel />
</Window.DataContext>
<Grid>
<TreeView Name="ScenariosTreeView" ItemsSource="{Binding Path=Cat, Mode=TwoWay}" Focusable="True" >
<TreeView.InputBindings>
<KeyBinding Key="Delete" Command="{Binding DeleteCommand}" CommandParameter="{Binding SelectedValue ,ElementName=ScenariosTreeView}" />
</TreeView.InputBindings>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExtended, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property="sotc:Behaviours.ExpandingBehaviour" Value="{Binding DataContext.ExpandingCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type sotc:ScenarioCategory}" ItemsSource="{Binding Path=ScenarioList}" >
<TextBlock Text="{Binding Path=Name}" Foreground="Black" IsEnabled="True" Focusable="True"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type sotc:Scenario}" >
<TextBlock Text="{Binding Path=Name, Mode=TwoWay}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</Window>
C#
公共类ViewModelBase:INotifyPropertyChanged
{
public void OnPropertyChanged([CallerMemberName]字符串名称=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(名称));
}
公共事件属性更改事件处理程序属性更改;
}
公共类MainWindowViewModel:ViewModelBase
{
公共ICommand ExpandingCommand{get;set;}
私有void executeexpanding命令(对象obj)
{
Console.WriteLine(@“扩展”);
}
私有布尔CANEXECUTEEEXPANDING命令(对象obj)
{
返回true;
}
公共主窗口视图模型()
{
ExpandingCommand=newrelaycommand(ExecuteExpandingCommand、CanExecuteExpandingCommand);
Cat=新的可观察集合(新场景类别[]
{
新场景类别{Name=“C1”},新场景类别{Name=“C2”},新场景类别{Name=“C3”}
});
}
公共可观测集合Cat{get;set;}
}
公共类场景类别:ViewModelBase
{
字符串\u名称;
公共字符串名
{
获取{return\u name;}
设置{u name=value;OnPropertyChanged();}
}
布尔扩展;
公共事业扩大了
{
获取{return\u isExtended;}
设置
{
_isExtended=值;
Console.WriteLine(@“扩展集”);
OnPropertyChanged();
}
}
布尔乌当选;
公选学校
{
获取{return}isSelected;}
设置
{
_isSelected=值;
控制台写入线(@“IsSelected set”);
OnPropertyChanged();
}
}
公共ObservableCollection场景列表{get;set;}
公共场景类别()
{
ScenarioList=new ObservableCollection(新场景[]{new Scenario{Name=“1”},新场景{Name=“2”},新场景{Name=“3”});
}
}
公共类场景:ViewModelBase
{
字符串\u名称;
公共字符串名
{
获取{return\u name;}
设置{u name=value;OnPropertyChanged();}
}
布尔扩展;
公共事业扩大了
{
获取{return\u isExtended;}
设置
{
_isExtended=值;
OnPropertyChanged();
}
}
布尔乌当选;
公选学校
{
获取{return}isSelected;}
设置
{
_isSelected=值;
OnPropertyChanged();
}
}
}
公众静态阶级行为
{
公共静态只读从属属性ExpandingBehaviorProperty=
DependencyProperty.RegisterAttached(“扩展行为”)、typeof(ICommand)、typeof(行为),
新属性元数据(OneExpandingBehavior已更改);
公共静态void setExpandingBehavior(DependencyObject o、ICommand值)
{
o、 SetValue(ExpandingBehavior属性,值);
}
公共静态ICommand GetExpandingBehavior(DependencyObject o)
{
返回(ICommand)o.GetValue(ExpandingBehavior属性);
}
私有静态void OneExpandingBehavior已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
TreeViewItem tvi=d作为TreeViewItem;
如果(tvi!=null)
{
ICommand ic=e.NewValue作为ICommand;
如果(ic!=null)
{
tvi.扩展+=(s,a)=>
{
if(ic.CanExecute(a))
{
ic.执行(a);
}
a、 已处理=正确;
};
}
}
}
}
公共类中继命令:ICommand
{
私人行动执行;
私人职能执行;
公共事件事件处理程序CanExecuteChanged
{
添加{CommandManager.RequerySuggested+=value;}
删除{CommandManager.RequerySuggested-=value;}
}
公共RelayCommand(执行操作,Func canExecute=null)
{
this.execute=execute;
this.canExecute=canExecute;
}
公共布尔CanExecute(对象参数)
{
返回this.canExecute==null | | this.canExecute(参数);
}
public void Execute(对象参数)
{
执行(参数);
}
}
找到了答案。如果事件放置在表示为treeviewItem的对象中,而不是视图模型中,则会触发该事件 您的场景
对象是您的视图模型吗?有一个列表,其中viewmodel和treeview显示列表使用模板绑定
和非绑定
当您在树上单击时,您的XAML看起来很好,并且应在viewmodel中设置IsExtended和IsSelected属性。您可以在VisualStudio中查看输出窗口,可能存在绑定错误,例如
public class ViewModelBase : INotifyPropertyChanged
{
public void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class MainWindowViewModel : ViewModelBase
{
public ICommand ExpandingCommand { get; set; }
private void ExecuteExpandingCommand(object obj)
{
Console.WriteLine(@"Expanded");
}
private bool CanExecuteExpandingCommand(object obj)
{
return true;
}
public MainWindowViewModel()
{
ExpandingCommand = new RelayCommand(ExecuteExpandingCommand, CanExecuteExpandingCommand);
Cat = new ObservableCollection<ScenarioCategory>(new ScenarioCategory[]
{
new ScenarioCategory { Name = "C1" }, new ScenarioCategory { Name = "C2" }, new ScenarioCategory { Name = "C3" }
});
}
public ObservableCollection<ScenarioCategory> Cat { get; set; }
}
public class ScenarioCategory : ViewModelBase
{
string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(); }
}
bool _isExtended;
public bool IsExtended
{
get { return _isExtended; }
set
{
_isExtended = value;
Console.WriteLine(@"IsExtended set");
OnPropertyChanged();
}
}
bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
Console.WriteLine(@"IsSelected set");
OnPropertyChanged();
}
}
public ObservableCollection<Scenario> ScenarioList { get; set; }
public ScenarioCategory()
{
ScenarioList = new ObservableCollection<Scenario>(new Scenario[] { new Scenario { Name = "1" }, new Scenario { Name = "2" }, new Scenario { Name = "3" } });
}
}
public class Scenario : ViewModelBase
{
string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(); }
}
bool _isExtended;
public bool IsExtended
{
get { return _isExtended; }
set
{
_isExtended = value;
OnPropertyChanged();
}
}
bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged();
}
}
}
public static class Behaviours
{
public static readonly DependencyProperty ExpandingBehaviourProperty =
DependencyProperty.RegisterAttached("ExpandingBehaviour", typeof(ICommand), typeof(Behaviours),
new PropertyMetadata(OnExpandingBehaviourChanged));
public static void SetExpandingBehaviour(DependencyObject o, ICommand value)
{
o.SetValue(ExpandingBehaviourProperty, value);
}
public static ICommand GetExpandingBehaviour(DependencyObject o)
{
return (ICommand)o.GetValue(ExpandingBehaviourProperty);
}
private static void OnExpandingBehaviourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TreeViewItem tvi = d as TreeViewItem;
if (tvi != null)
{
ICommand ic = e.NewValue as ICommand;
if (ic != null)
{
tvi.Expanded += (s, a) =>
{
if (ic.CanExecute(a))
{
ic.Execute(a);
}
a.Handled = true;
};
}
}
}
}
public class RelayCommand : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
}