2009-11-12 5 views
8

Ho un ViewModel sopra un controllo TreeView WPF. Voglio che ViewModel sia in grado di impostare e leggere l'oggetto SelectedItem da TreeView. Tuttavia, la proprietà SelectedItem di TreeView non è associabile.TreeView Sync to SelectedItem in View Modello

Sono in grado di impostare e ottenere l'elemento selezionato nel codice sottostante (utilizzando ItemContainerGenerator e TreeViewItem.IsSelected = true) ma questo porta ad alcune brutte comunicazioni tra il codice sottostante e ViewModel.

Qualcuno ha una soluzione pulita per questo?

+1

Hai mai risolto questo? Ho esattamente questo problema. – BrettRobi

+3

Penso che questa domanda sia duplicata di http://stackoverflow.com/questions/1000040/selecteditem-in-a-wpf-treeview –

risposta

0

È possibile utilizzare un qualche tipo di classe proxy per associare proprietà SelectedItem di In e Out immobili di proprietà si legano ai vostri ViewModel:

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

posso fornire un esempio. Quello che faccio è impostare la proprietà IsSelected di un TreeViewItem (non lo TreeView stesso) nel modello di vista, perché è possibile associare a questo.

Nel mio modello di vista ho una proprietà ElementInViewModel che è una struttura di dati che forma un albero stesso. Io uso un HierarchicalDataTemplate nel mio Xaml per visualizzarlo. L'oggetto dati stesso è di tipo YourDomainType e i relativi elementi figlio (dello stesso tipo) sono nella proprietà ChildElements.

Nel modello di vista, ho impostato la proprietà IsExpanded e IsSelected della mia classe di dati YourDomainType. A causa dello stile definito di seguito, passeranno questa impostazione allo TreeViewItem.

Funziona per voi?

<UserControl> 

    <UserControl.Resources>   
     <CollectionViewSource Source="{Binding Path=ElementInViewModel}" x:Key="Cvs"> 
     </CollectionViewSource> 

     <HierarchicalDataTemplate DataType="{x:Type DomainModel:YourDomainType}" 
            ItemsSource="{Binding Path=ChildElements}"> 
      <TextBlock Text="{Binding Path=Name}"/>    
     </HierarchicalDataTemplate>   

     <Style TargetType="{x:Type TreeViewItem}"> 
      <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> 
      </Setter> 
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> 
      </Setter>    
     </Style> 

    </UserControl.Resources> 


    <DockPanel> 
     <TreeView ItemsSource="{Binding Source={StaticResource Cvs}}"/> 
    </DockPanel> 

</UserControl>