2009-11-12 7 views
8

Ich habe ein ViewModel über einem WPF TreeView-Steuerelement. Ich möchte, dass das ViewModel das SelectedItem aus der TreeView setzen und lesen kann. Die SelectedItem-Eigenschaft der TreeView ist jedoch nicht bindbar.TreeView-Sync zu SelectedItem im Ansichtsmodell

Ich bin in der Lage, zu setzen und das ausgewählte Element im Code zu erhalten (mit ItemContainerGenerator und TreeViewItem.IsSelected = true), aber dies führt zu einigen hässlichen Kommunikation zwischen dem Code hinter und dem ViewModel.

Hat jemand eine saubere Lösung dafür?

+1

Haben Sie das jemals gelöst? Ich habe genau dieses Problem. – BrettRobi

+3

Ich denke, diese Frage ist ein Duplikat von http://stackoverflow.com/questions/1000040/selecteitem-in-a-wpf-treeview –

Antwort

0

können Sie irgendeine Art von Proxy-Klasse verwenden In der Schaden- und Out-Eigenschaft bindet an Ihr Ansichtsmodell SelectedItem-Eigenschaft zu binden:

public class Proxy : FrameworkElement 
    { 
    public static readonly DependencyProperty InProperty; 
    public static readonly DependencyProperty OutProperty; 

    public Proxy() 
    { 
     Visibility = Visibility.Collapsed; 
    } 

    static Proxy() 
    { 
     var inMetadata = new FrameworkPropertyMetadata(
      delegate(DependencyObject p, DependencyPropertyChangedEventArgs args) 
       { 
        if (null != BindingOperations.GetBinding(p, OutProperty)) 
        { 
         var proxy = p as Proxy; 
         if (proxy != null) 
          proxy.Out = args.NewValue; 
        } 
       }); 

     inMetadata.BindsTwoWayByDefault = false; 
     inMetadata.DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; 

     InProperty = DependencyProperty.Register("In", 
               typeof (object), 
               typeof (Proxy), 
               inMetadata); 

     var outMetadata = new FrameworkPropertyMetadata(
      delegate(DependencyObject p, DependencyPropertyChangedEventArgs args) 
       { 
        ValueSource source = DependencyPropertyHelper.GetValueSource(p, args.Property); 

        if (source.BaseValueSource != BaseValueSource.Local) 
        { 
         var proxy = p as Proxy; 
         if (proxy != null) 
         { 
          var expected = proxy.In; 
          if (!ReferenceEquals(args.NewValue, expected)) 
          { 
           Dispatcher.CurrentDispatcher.BeginInvoke(
            DispatcherPriority.DataBind, new Action(delegate 
                       { 
                        proxy.Out = proxy.In; 
                       })); 
          } 
         } 
        } 
       }); 

     outMetadata.BindsTwoWayByDefault = true; 
     outMetadata.DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; 

     OutProperty = DependencyProperty.Register("Out", 
                typeof (object), 
                typeof (Proxy), 
                outMetadata); 
    } 

    public object In 
    { 
     get { return GetValue(InProperty); } 
     set { SetValue(InProperty, value); } 
    } 

    public object Out 
    { 
     get { return GetValue(OutProperty); } 
     set { SetValue(OutProperty, value); } 
    } 
} 
<Proxy In="{Binding ElementName=Tree, Path=SelectedItem}" Out="{Binding SelectedItem, UpdateSourceTrigger=PropertyChanged}"/> 
<TreeView x:Name="Tree" ItemsSource="{Binding Path=Items}"/> 
1

ich ein Beispiel zur Verfügung stellen kann. Was ich mache, ist die IsSelected Eigenschaft eines TreeViewItem (nicht die TreeView selbst) im View-Modell, weil Sie daran binden können.

In meiner Ansicht Modell habe ich eine Eigenschaft ElementInViewModel, die eine Datenstruktur ist, die selbst einen Baum bildet. Ich verwende eine in meinem Xaml, um es anzuzeigen. Das Datenobjekt selbst ist vom Typ YourDomainType und seine untergeordneten Elemente (des gleichen Typs) befinden sich in seiner ChildElements-Eigenschaft.

Im Ansichtsmodell habe ich die IsExpanded und IsSelected Eigenschaft meiner Datenklasse YourDomainType festgelegt. Aufgrund des unten definierten Stils wird diese Einstellung an die TreeViewItem übergeben.

Funktioniert das für Sie?