2016-08-18 2 views
0

WPF TreeViewコントロールとMVVMデザインパターンを使用して、マスター/詳細ビュー(Windowsエクスプローラとよく似ています)を実装したいと考えています。 TreeViewコントロールの処理に関しては安全ですが、Masterビュー(TreeView)で現在選択されているアイテムをDataContextとしてDetailビュー(実際にはListViewを保持するUserControl)に渡す方法がわかりません。私はそのXAMLをしたいと思っています。誰もそれをする方法を知っていますか?WPF MVVMツリービューコントロールを使用したマスター詳細ビュー

明確にするために、少しアドレスブックのデモをここに掲載します。

これは基本的にクライアント領域をグリッドで3つの列に分割するメインウィンドウビューです。左のものはツリー、中央のものはスプリッタ、右のものは詳細ビューを保持します。

<Window.Resources> 
    <HierarchicalDataTemplate DataType="{x:Type vm:Address}" ItemsSource="{Binding Residents}"> 
     <TextBlock> 
      <TextBlock.Text> 
       <MultiBinding StringFormat="{}{0}, {1}, {2}"> 
        <Binding Path="Street"/> 
        <Binding Path="City"/> 
        <Binding Path="ZipCode"/> 
       </MultiBinding> 
      </TextBlock.Text> 
     </TextBlock> 
    </HierarchicalDataTemplate> 

    <DataTemplate DataType="{x:Type vm:Resident}"> 
     <TextBlock> 
      <TextBlock.Text> 
       <MultiBinding StringFormat="{}{0} {1}"> 
        <Binding Path="FirstName"/> 
        <Binding Path="LastName"/> 
       </MultiBinding> 
      </TextBlock.Text> 
     </TextBlock> 
    </DataTemplate> 
</Window.Resources> 

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="150"/> 
     <ColumnDefinition Width="5"/> 
     <ColumnDefinition Width="*"/> 
    </Grid.ColumnDefinitions> 
    <TreeView BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Addresses}"/> 
    <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" /> 
    <v:ResidentDetailView Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DataContext="???"/> 
</Grid> 

あなたは私が詳細ビューにDataContextのようツリーで選択した項目を渡したい最後の行で見ることができるように。

これは、詳細は、ユーザーコントロールであるかを表示次のとおりです。

<ListView ItemsSource="{Binding Residents}"> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn DisplayMemberBinding="{Binding FirstName}" Header="FirstName" Width="100"/> 
      <GridViewColumn DisplayMemberBinding="{Binding LastName}" Header="LastName" Width="100"/> 
     </GridView> 
    </ListView.View> 
</ListView> 

そして最後に、私がメインと詳細ビュー間で共有したいメインウィンドウのビューモデル:あなたのための

public class Resident 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

public class Address 
{ 
    public string Street { get; set; } 
    public string City { get; set; } 
    public int ZipCode { get; set; } 
    public List<Resident> Residents { get; } = new List<Resident>(); 
} 

public class MainWindowViewModel 
{ 
    public ObservableCollection<Address> Addresses { get; } = new ObservableCollection<Address>(); 

    public MainWindowViewModel() 
    { 
     var a = new Address {Street = "Broadway 1", City = "New York", ZipCode = 12345}; 
     a.Residents.Add(new Resident { FirstName = "John", LastName = "Miller" }); 
     a.Residents.Add(new Resident { FirstName = "Lisa", LastName = "Miller" }); 
     Addresses.Add(a); 
     a = new Address { Street = "Wall Street 1", City = "New York", ZipCode = 12345 }; 
     a.Residents.Add(new Resident { FirstName = "Paul", LastName = "Walker" }); 
     a.Residents.Add(new Resident { FirstName = "Frank", LastName = "Brown" }); 
     a.Residents.Add(new Resident { FirstName = "Mark", LastName = "Smith" }); 
     Addresses.Add(a); 
     a = new Address { Street = "Market Street 1", City = "San Francisco", ZipCode = 23456 }; 
     a.Residents.Add(new Resident { FirstName = "Jack", LastName = "Ness" }); 
     a.Residents.Add(new Resident { FirstName = "Joe", LastName = "Jackson" }); 
     a.Residents.Add(new Resident { FirstName = "Jill", LastName = "Baude" }); 
     Addresses.Add(a); 
     a = new Address { Street = "Rodeo Drive 1", City = "Los Angeles", ZipCode = 34567 }; 
     a.Residents.Add(new Resident { FirstName = "Roger", LastName = "Water" }); 
     a.Residents.Add(new Resident { FirstName = "Andy", LastName = "Murray" }); 
     a.Residents.Add(new Resident { FirstName = "Peter", LastName = "Hammer" }); 
     a.Residents.Add(new Resident { FirstName = "Lola", LastName = "White" }); 
     Addresses.Add(a); 
    } 
} 

感謝を助けて。 Johannes

+0

長い質問ですが、単に「マスタービューで現在選択されているアイテムをどのように渡すことができないのかわかりません」*と尋ねるだけです。 [this](http://stackoverflow.com/q/1000040/1997232)を参照してください。 – Sinatr

+0

私はここで見つけたのような答えを得ることを望んでいます。http://stackoverflow.com/questions/15206671/master-detail-view-ツリービューを使用します。残念ながらそれは動作していません – Johannes

+0

私はブレンドの相互作用を使用して、 DetailsVMを更新し、詳細ビューを更新します。しかし、私はまだこれがより簡単に行われることを願っています – Johannes

答えて

0

これは確かにあなたが他のスレッドで見つけた種類のバインディングで可能です。

ただし、現在選択されている項目のプロパティをViewModelに追加するだけです。おそらく、(あなたは、彼らが何かをクリックすると詳細が表示変更したい場合は、例えば)とにかくそれを追跡するためには良いでしょう:

public class MainWindowViewModel 
{ 
    public ObservableCollection<Address> Addresses { get; } = new ObservableCollection<Address>(); 

    public Address SelectedAddress { //get and set with INotifyPropertyChanged } 

    public MainWindowViewModel() 
    { 
     ... 
    } 
} 

とビューで:

<TreeView BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Addresses}" SelectedItem="{Binding SelectedAddress}"/> 
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" /> 
<v:ResidentDetailView Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DataContext="{Binding SelectedAddress}"/> 
+0

はい、それは私が探していたものです。ありがとう。 – Johannes

関連する問題