2016-02-12 69 views
3

我已经想通了绑定动态树视图与ReactiveUI内用户控件方式分层数据源(树视图)。如何使用ReactiveUI与

但是... 顶层结合HierachicalDataSource在XAML没有后面的代码,我需要直接设置的ItemsSource,而不是使用this.OneWayBind%的一般模式为ReactiveUI结合。

所以,我的问题是:我错过了在ReactiveUI框架,让我和this.OneWayBind结合并移动到HierachicalDataTemplete后面的代码或定制用户控制的东西吗?

特别是 - OneWayBind是否支持Hierarchical Data Templates的另一种重载或在使用时抑制呼叫的数据模板生成?

更新 我添加选择的项目,以及扩大和选择,以我的测试项目程序上的支持,但我有一个样式到XAML。我想,以取代用一个简单的RxUI绑定为好。更新的例子。

下面是关键细节:

树控件在主视图中

<TreeView Name="FamilyTree" > 
       <TreeView.Resources> 
        <Style TargetType="{x:Type TreeViewItem}"> 
         <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/> 
         <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/> 
        </Style> 
        <HierarchicalDataTemplate DataType="{x:Type local:TreeItem}" ItemsSource="{Binding Children}"> 
         <reactiveUi:ViewModelViewHost ViewModel="{Binding ViewModel}"/> 
        </HierarchicalDataTemplate> 
       </TreeView.Resources> 
      </TreeView> 

主视图代码后面

 public partial class MainWindow : Window, IViewFor<MainVM> 
     { 
      public MainWindow() 
      { 
       InitializeComponent(); 
       //build viewmodel 
       ViewModel = new MainVM(); 
       //Register views 
       Locator.CurrentMutable.Register(() => new PersonView(), typeof(IViewFor<Person>)); 
       Locator.CurrentMutable.Register(() => new PetView(), typeof(IViewFor<Pet>)); 
       //NB. ! Do not use 'this.OneWayBind ... ' for the top level binding to the tree view 
       //this.OneWayBind(ViewModel, vm => vm.Family, v => v.FamilyTree.ItemsSource); 
       FamilyTree.ItemsSource = ViewModel.Family; 
    } 
... 
} 

MainViewModel

public class MainVM : ReactiveObject 
     {  
      public MainVM() 
      { 
       var bobbyJoe = new Person("Bobby Joe", new[] { new Pet("Fluffy") }); 
       var bob = new Person("Bob", new[] { bobbyJoe }); 
       var littleJoe = new Person("Little Joe"); 
       var joe = new Person("Joe", new[] { littleJoe }); 
       Family = new ReactiveList<TreeItem> { bob, joe };         
      _addPerson = ReactiveCommand.Create(); 
      _addPerson.Subscribe(_ => 
      { 
       if (SelectedItem == null) return; 
       var p = new Person(NewName); 
       SelectedItem.AddChild(p); 
       p.IsSelected = true; 
       p.ExpandPath(); 
      }); 
    } 
    public ReactiveList<TreeItem> Family { get; } 
    ... 
    } 

TreeItem基类

public abstract class TreeItem : ReactiveObject 
{ 
    private readonly Type _viewModelType; 

    bool _isExpanded; 
    public bool IsExpanded 
    { 
     get { return _isExpanded; } 
     set { this.RaiseAndSetIfChanged(ref _isExpanded, value); } 
    } 

    bool _isSelected; 
    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set { this.RaiseAndSetIfChanged(ref _isSelected, value); } 
    } 

    private TreeItem _parent; 

    protected TreeItem(IEnumerable<TreeItem> children = null) 
    { 

     Children = new ReactiveList<TreeItem>(); 
     if (children == null) return; 
     foreach (var child in children) 
     { 
      AddChild(child); 
     } 
    } 

    public abstract object ViewModel { get; } 
    public ReactiveList<TreeItem> Children { get; } 

    public void AddChild(TreeItem child) 
    { 
     child._parent = this; 
     Children.Add(child); 
    } 

    public void ExpandPath() 
    { 
     IsExpanded = true; 
     _parent?.ExpandPath(); 
    } 
    public void CollapsePath() 
    { 
     IsExpanded = false; 
     _parent?.CollapsePath(); 
    } 
} 

Person类

public class Person : TreeItem 
    { 
     public string Name { get; set; } 
     public Person(string name, IEnumerable<TreeItem> children = null) 
      : base(children) 
     { 
      Name = name; 
     } 
     public override object ViewModel => this; 
    } 

人称视角用户控制

<UserControl x:Class="TreeViewInheritedItem.PersonView"... >     
    <StackPanel> 
     <TextBlock Name="PersonName"/> 
    </StackPanel> 
</UserControl> 

人视图代码后面

public partial class PersonView : UserControl, IViewFor<Person> 
    { 
     public PersonView() 
     { 
      InitializeComponent(); 
      this.OneWayBind(ViewModel, vm => vm.Name, v => v.PersonName.Text); 
     } 
     ... 
    } 

宠物工作方式相同的人。

而整个项目是在这里ReactiveUI Tree view Sample

回答

0

我回顾了ReactiveUI源,这是做到这一点的唯一方法。绑定辅助方法总是用一个DataTemplate而不是HierarchicalDataTemplate。

所以这种方法将使用顶级XAML绑定,然后让您在所有TreeView项目上使用ReactiveUI绑定。

我会看到有关创建pull请求来处理这种边缘情况。

谢谢, 克里斯