WPF-treeview에서 선택된 항목을 어떻게 검색합니까? 바인딩하기 때문에 XAML 에서이 작업을 수행하고 싶습니다.
당신은 것을 생각 SelectedItem
하는하지만 분명히 존재하지 않는 읽기 전용 따라서 사용할 수없는 것입니다.
이것이 내가하고 싶은 일입니다.
<TreeView ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource ClusterTemplate}"
SelectedItem="{Binding Path=Model.SelectedCluster}" />
SelectedItem
내 모델의 속성에 바인딩하고 싶습니다 .
그러나 이것은 나에게 오류를 준다 :
‘SelectedItem’속성은 읽기 전용이며 마크 업에서 설정할 수 없습니다.
편집 :
좋아, 이것이 내가 해결 한 방법입니다.
<TreeView
ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource HoofdCLusterTemplate}"
SelectedItemChanged="TreeView_OnSelectedItemChanged" />
내 xaml의 코드 숨김 파일에서 :
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
Model.SelectedCluster = (Cluster)e.NewValue;
}
답변
나는 이것이 이미 대답을 받아 들였다는 것을 알고 있지만 문제를 해결하기 위해 이것을 합쳤다. 델타의 솔루션과 비슷한 아이디어를 사용하지만 TreeView를 서브 클래스화할 필요는 없습니다.
public class BindableSelectedItemBehavior : Behavior<TreeView>
{
#region SelectedItem Property
public object SelectedItem
{
get { return (object)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));
private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var item = e.NewValue as TreeViewItem;
if (item != null)
{
item.SetValue(TreeViewItem.IsSelectedProperty, true);
}
}
#endregion
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
if (this.AssociatedObject != null)
{
this.AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
}
}
private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
this.SelectedItem = e.NewValue;
}
}
그런 다음 XAML에서 다음과 같이 사용할 수 있습니다.
<TreeView>
<e:Interaction.Behaviors>
<behaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
</e:Interaction.Behaviors>
</TreeView>
잘만되면 그것은 누군가를 도울 것입니다!
답변
이 속성이 존재합니다 : TreeView.SelectedItem
그러나 읽기 전용이므로 바인딩을 통해 할당 할 수 없으며 검색 만 가능합니다.
답변
필요한 경우 외부 속성없이 첨부 된 속성으로 답변하십시오!
바인딩 가능하고 게터와 세터가있는 연결된 속성을 만들 수 있습니다.
public class TreeViewHelper
{
private static Dictionary<DependencyObject, TreeViewSelectedItemBehavior> behaviors = new Dictionary<DependencyObject, TreeViewSelectedItemBehavior>();
public static object GetSelectedItem(DependencyObject obj)
{
return (object)obj.GetValue(SelectedItemProperty);
}
public static void SetSelectedItem(DependencyObject obj, object value)
{
obj.SetValue(SelectedItemProperty, value);
}
// Using a DependencyProperty as the backing store for SelectedItem. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.RegisterAttached("SelectedItem", typeof(object), typeof(TreeViewHelper), new UIPropertyMetadata(null, SelectedItemChanged));
private static void SelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is TreeView))
return;
if (!behaviors.ContainsKey(obj))
behaviors.Add(obj, new TreeViewSelectedItemBehavior(obj as TreeView));
TreeViewSelectedItemBehavior view = behaviors[obj];
view.ChangeSelectedItem(e.NewValue);
}
private class TreeViewSelectedItemBehavior
{
TreeView view;
public TreeViewSelectedItemBehavior(TreeView view)
{
this.view = view;
view.SelectedItemChanged += (sender, e) => SetSelectedItem(view, e.NewValue);
}
internal void ChangeSelectedItem(object p)
{
TreeViewItem item = (TreeViewItem)view.ItemContainerGenerator.ContainerFromItem(p);
item.IsSelected = true;
}
}
}
해당 클래스를 포함하는 네임 스페이스 선언을 XAML에 추가하고 다음과 같이 바인딩합니다 (로컬은 네임 스페이스 선언의 이름을 지정한 방법입니다).
<TreeView ItemsSource="{Binding Path=Root.Children}" local:TreeViewHelper.SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}">
</TreeView>
이제 선택한 항목을 바인딩하고 요구 사항이 발생할 경우 뷰 모델에서 프로그래밍 방식으로 변경하도록 설정할 수 있습니다. 물론 이것은 특정 속성에 INotifyPropertyChanged를 구현한다고 가정 한 것입니다.
답변
글쎄, 나는 해결책을 찾았다. MVVM이 작동하도록 혼란을 옮깁니다.
먼저이 클래스를 추가하십시오.
public class ExtendedTreeView : TreeView
{
public ExtendedTreeView()
: base()
{
this.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(___ICH);
}
void ___ICH(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if (SelectedItem != null)
{
SetValue(SelectedItem_Property, SelectedItem);
}
}
public object SelectedItem_
{
get { return (object)GetValue(SelectedItem_Property); }
set { SetValue(SelectedItem_Property, value); }
}
public static readonly DependencyProperty SelectedItem_Property = DependencyProperty.Register("SelectedItem_", typeof(object), typeof(ExtendedTreeView), new UIPropertyMetadata(null));
}
이것을 xaml에 추가하십시오.
<local:ExtendedTreeView ItemsSource="{Binding Items}" SelectedItem_="{Binding Item, Mode=TwoWay}">
.....
</local:ExtendedTreeView>
답변
OP가 기대하는 것보다 조금 더 대답합니다 …하지만 적어도 일부는 도울 수 있기를 바랍니다.
변경 ICommand
될 때마다을 실행 SelectedItem
하려면 이벤트에 명령을 바인딩 할 수 있으며 더 이상 속성 SelectedItem
을 사용할 ViewModel
필요가 없습니다.
그렇게하려면 :
1- 참조 추가 System.Windows.Interactivity
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
2- 명령을 이벤트에 바인딩 SelectedItemChanged
<TreeView x:Name="myTreeView" Margin="1"
ItemsSource="{Binding Directories}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding SomeCommand}"
CommandParameter="
{Binding ElementName=myTreeView
,Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemTemplate>
<!-- ... -->
</TreeView.ItemTemplate>
</TreeView>
답변
이는 바인딩과 GalaSoft MVVM Light 라이브러리의 EventToCommand 만 사용하여 ‘보다 효율적인’방식으로 수행 할 수 있습니다. VM에서 선택한 항목이 변경 될 때 호출 될 명령을 추가하고 필요한 조치를 수행하도록 명령을 초기화하십시오. 이 예제에서는 RelayCommand를 사용했으며 SelectedCluster 속성 만 설정합니다.
public class ViewModel
{
public ViewModel()
{
SelectedClusterChanged = new RelayCommand<Cluster>( c => SelectedCluster = c );
}
public RelayCommand<Cluster> SelectedClusterChanged { get; private set; }
public Cluster SelectedCluster { get; private set; }
}
그런 다음 xaml에 EventToCommand 동작을 추가하십시오. 블렌드를 사용하면 정말 쉽습니다.
<TreeView
x:Name="lstClusters"
ItemsSource="{Binding Path=Model.Clusters}"
ItemTemplate="{StaticResource HoofdCLusterTemplate}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding SelectedClusterChanged}" CommandParameter="{Binding ElementName=lstClusters,Path=SelectedValue}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TreeView>
답변
복잡한 작업 … Caliburn Micro 사용 (http://caliburnmicro.codeplex.com/)
전망:
<TreeView Micro:Message.Attach="[Event SelectedItemChanged] = [Action SetSelectedItem($this.SelectedItem)]" />
뷰 모델 :
public void SetSelectedItem(YourNodeViewModel item) {};
