2017-03-01 8 views
0

Foreach treeview-item私は独自のデータグリッドを持っています。ツリービューのアイテムとデータグリッドは、バインディングで埋められます。複数のデータグリッドのSelectedItemを取得するには?

テキストボックスでは、データグリッドの選択項目にバインドされています。しかし、これらのテキストボックスへのバインドは、最初のDataGridでのみ機能します。

<TextBox Text="{Binding PlaceList/SelectedMachine.Name, ValidatesOnDataErrors=True}" /> 

I:他のすべてのデータグリッドは、テキストボックスにのSelectedItemを転送しません:

ここwrong binding

は、データグリッドとツリービューで:テキストボックスここ

  <TreeView ItemsSource="{Binding Path=PlaceList}"> 
       <TreeView.ItemTemplate> 
        <DataTemplate> 
         <TreeViewItem Header="{Binding Path=Name}"> 
          <DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
             SelectionUnit="FullRow" 
             SelectedItem="{Binding SelectedMachine, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
             AutoGenerateColumns="True" 
             IsSynchronizedWithCurrentItem="True" 
             SelectionMode="Single"> 
          </DataGrid> 
         </TreeViewItem> 
        </DataTemplate> 
       </TreeView.ItemTemplate> 
      </TreeView> 

ですMvvmLightで作業しています。

public ObservableCollection<PlaceModel> PlaceList { get; set; } = new ObservableCollection<PlaceModel>(); 

    public ObjectInspectorViewModel() 
    { 
     PlaceList = PlaceModel.GetPlaces(BaseResourcePaths.PlacesCsv); 
    } 

私の場所、モデルS:私のViewModelはPlaceListを保持している

public class PlaceModel 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } = "_CurrentObjectName"; 
    public string Length { get; set; } 
    public string Width { get; set; } 
    public string Height { get; set; } 
    public ObservableCollection<MachineModel> MachinesInPlace { get; set; } 
    public MachineModel SelectedMachine { get; set; } 

    public static ObservableCollection<PlaceModel> GetPlaces(string filepath) 
    { 
     [...] 
    } 
} 

私は何かを試してみたが、最後に、私はバグを修正する方法を知りません。どうしたの?私の提案は、プレースモデル内のプロパティ "SelectedMachine"です...

ここでは、Sebastian Richterの追加ソリューションを使用したサンプルプロジェクトを示します。 https://www.file-upload.net/download-12370581/DatagridTreeViewError.zip.html

+0

TreeviewでSelectedItemが必要なのではなく、それに基づいてテキストボックスへのバインディングを行いますか?それ以外の場合、バインディングは最初のインスタンスを取得しているだけで、ツリービューの選択時には更新されません。 – Josh

+0

あなたの返事のためのThx。私はウルの解決策を試みたが、それは仕事をしなかった。私はhttp://stackoverflow.com/a/3535089のようにSelectedItemプロパティを使ってtreeviewコントロールを拡張しなければなりませんでした。私は次のXAMLで終わった:http://pastebin.com/VVgBtCqR問題は、ツリービューは、場所の完全なリストを保持し、各場所では、異なる(データグリッド)マシンのリストです。だから、treeview - select私はどのplace-listが選択されたかを知ることができますが、それらのplace-list内のどのマシンが選択されるのかはわかりません。または私は間違っていますか? – Chpo7234

答えて

1

INotifyPropertyChangedをあなたのクラスPlaceModelに実装することを忘れていないことは確かです。問題は選択を変更した後で、プロパティPlacemodel.SelectedMachineは更新されますが、この変更をビューに入力するイベントは発生しません。

MVVM Lightを使用しているため、既にこのインターフェイスを実装しているObservableObjectから派生することができます。 だからあなたPlaceModel次のコードに変更します。私はあなたがそれを設定するために、バインディングをごObservableCollection(1つのリレーションに多く)からと結合するためにどの要素を知っていないと思います

public class PlaceModel : ObservableObject 
{ 
    private MachineModel _selectedMachine; 
    public int Id { get; set; } 
    public string Name { get; set; } = "_CurrentObjectName"; 
    public string Length { get; set; } 
    public string Width { get; set; } 
    public string Height { get; set; } 
    public ObservableCollection<MachineModel> MachinesInPlace { get; set; } 

    public MachineModel SelectedMachine 
    { 
     get 
     { 
      return _selectedMachine; 
     } 

     set 
     { 
      // raises Event PropertyChanged after setting value 
      Set(ref _selectedMachine, value); 
     } 
    } 

    public static ObservableCollection<PlaceModel> GetPlaces(string filepath) 
    { 
    [...] 
} 

編集TextBoxの参照として

だから、モデルからSelectedMachineプロパティを削除し、バックのViewModelにそれを追加しよう:

<Grid x:Name="LayoutRoot"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="2*"></RowDefinition> 
     <RowDefinition></RowDefinition> 
    </Grid.RowDefinitions> 

    <!-- Row #1 --> 
    <Grid> 
     <!-- TreeView und DataGrids--> 
     <TreeView ItemsSource="{Binding Path=PlaceList}"> 
      <TreeView.ItemTemplate> 
       <DataTemplate> 
        <TreeViewItem Header="{Binding Path=Name}"> 
         <DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
            SelectedItem="{Binding DataContext.SelectedMachine, RelativeSource={RelativeSource AncestorType=Window},Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
        </TreeViewItem> 
       </DataTemplate> 
      </TreeView.ItemTemplate> 
     </TreeView> 
    </Grid> 

    <!-- Row #2 --> 
    <Grid Grid.Row="1"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition></ColumnDefinition> 
      <ColumnDefinition Width="2*"></ColumnDefinition> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition></RowDefinition> 
      <RowDefinition></RowDefinition> 
     </Grid.RowDefinitions> 

     <Label Grid.Row="0" 
       Content="ID" /> 
     <!-- Textboxen aktualisieren nur bei Auswahl der ersten Datagrid --> 
     <TextBox Grid.Column="2" 
       Grid.Row="0" 
       Text="{Binding SelectedMachine.Id, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
     <Label Grid.Row="1" 
       Content="Name" /> 
     <TextBox Grid.Column="2" 
       Grid.Row="1" 
       Text="{Binding SelectedMachine.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 
    </Grid> 
</Grid> 

class ViewModel : ViewModelBase 
{ 
    ... 
    private MachineModel _selectedMachine; 
    public MachineModel SelectedMachine 
    { 
     get 
     { 
      return _selectedMachine; 
     } 
     set 
     { 
     // raises Event PropertyChanged after setting value 
     Set(ref _selectedMachine, value); 
     } 
    } 
    ... 
} 

はまた、次のコード(私はあなたの例のプロジェクトを使用)にあなたのXAMLを変更

キーは、SelectedItemの正しいDataContextを設定することでした。このために私はXAMLコードに続いて使用しました:

<DataGrid ItemsSource="{Binding MachinesInPlace, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
            SelectedItem="{Binding DataContext.SelectedMachine, RelativeSource={RelativeSource AncestorType=Window},Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> 

この例では、あなたのサンプルプロジェクトが正しくTextBoxを更新します。

+0

ありがとうございます。実際には 'InotifyPropertyChanged'-interface /' ObservableObject'を忘れてしまいました。このアイデアを自分のコードに追加しましたが、問題を解決できませんでした。私の質問では、問題をより正確に示すプロジェクト例を追加しました。むしろ 'SelectedMachine'は' PlaceModel'の外になければならないと思います。しかし、私がプロパティ 'PlaceList'と' SelectedMachine'を私のviewmodelに入れると、上記のツリービューに 'PlaceList'を設定しているので、私のxaml-datagridの' SelectedMachine'にアクセスできません:http://pastebin.com/ 20HwpPga – Chpo7234

+0

私の編集をご覧ください。 –

+0

私はあなたの努力に非常に感謝しています!問題のあるVisual Studioでは、バインディングウィンドウに「DataContext.SelectedMachine」というプロパティが表示されないため、手動で設定する必要があります。 [この写真](https://picload.org/image/rlcgogwr/binding2.png)を参照してください。私はウルの助けなしにそれを見つけることは決してないだろう、ありがとう! – Chpo7234

関連する問題