WPF树视图和数据网格选择已更改

时间:2016-09-29 03:59:51

标签: c# wpf

我正在使用TreeviewDataGrid

开展此WPF项目

左侧是树形结构,其中一些文档显示在数据网格的右侧。 如果我们在树视图中更改所选项,则数据网格显示应该更改。 所有文件应显示所有等等。 有人能指出我正确的方向吗?我在winforms中使用了一些视图模型。 在WPF中执行此操作似乎很难。我刚刚学习WPF。这是我到目前为止所做的。现在,我带入树的部分是一些帮助或网站将是好的

        <Grid ShowGridLines="False">


            <DataGrid Name="DataGrid1" AutoGenerateColumns="False" AlternatingRowBackground="AliceBlue">
                <DataGrid.Columns>

                    <DataGridTextColumn Header="Document Type Name" Binding="{Binding DocumentType.DocumentTypeName}" IsReadOnly="True"></DataGridTextColumn>
                    <DataGridTextColumn Header="Status" Binding="{Binding Name}" IsReadOnly="True"></DataGridTextColumn>
                    <DataGridTextColumn Header="Description" Binding="{Binding Description}" IsReadOnly="True"></DataGridTextColumn>

                    <DataGridTextColumn Header="Type" Binding="{Binding Type}" IsReadOnly="True"></DataGridTextColumn>

                </DataGrid.Columns>

            </DataGrid>
        </Grid>

    </StackPanel>

enter image description here

1 个答案:

答案 0 :(得分:1)

由于默认的TreeView不支持SelectedItem上的Binding,因此您必须执行一个丑陋的变通方法。对Treeview进行子类化并首先使其可绑定:

 public class TreeViewA : TreeView {

    public new static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(TreeViewA), new FrameworkPropertyMetadata(null, OnSelectedItemChanged));

    public TreeViewA() {
      base.SelectedItemChanged += this.OnTreeViewSelectedItemChanged;
      this.ItemContainerGenerator.StatusChanged += this.ItemContainerGeneratorOnStatusChanged;
    }

    public new object SelectedItem {
      get {
        return this.GetValue(SelectedItemProperty);
      }
      set {
        this.SetValue(SelectedItemProperty, value);
      }
    }

    private void ItemContainerGeneratorOnStatusChanged(object sender, EventArgs eventArgs) {
      if (this.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
        return;
      if (this.SelectedItem != null) {
        this.VisualSelectItem();
      }
    }

    private void VisualSelectItem() {
      var xx = (TreeViewItem)this.ItemContainerGenerator.ContainerFromItem(this.SelectedItem);
      if (xx == null)
        return;
      xx.IsSelected = true;
      xx.BringIntoView();
    }

    private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) {
      this.SelectedItem = e.NewValue;
    }

    private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
      if (e.NewValue != null) {
        (sender as TreeViewA)?.VisualSelectItem();
      }
    }

  }

接下来,Gui(示例)

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <local:TreeViewA ItemsSource="{Binding Documents}" SelectedItem="{Binding SelectedDocument, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
            <TreeView.ItemTemplate>
                <DataTemplate>
                    <WrapPanel>
                        <Image Source="whereever" Width="40" Height="40"/>
                        <TextBlock Text="{Binding Name}"/>
                    </WrapPanel>
                </DataTemplate>
            </TreeView.ItemTemplate>
        </local:TreeViewA>

        <DataGrid Grid.Column="1" ItemsSource="{Binding SubDocuments, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" AutoGenerateColumns="False">
            <DataGrid.Columns>

                <DataGridTextColumn Header="Document Type Name" Binding="{Binding DocumentTypeName}" IsReadOnly="True"></DataGridTextColumn>
                <DataGridTextColumn Header="Status" Binding="{Binding Name}" IsReadOnly="True"></DataGridTextColumn>
                <DataGridTextColumn Header="Description" Binding="{Binding Description}" IsReadOnly="True"></DataGridTextColumn>

                <DataGridTextColumn Header="Type" Binding="{Binding Type}" IsReadOnly="True"></DataGridTextColumn>

            </DataGrid.Columns>

        </DataGrid>
    </Grid>

我的文档示例模型:

public class Document {

    public string Name {
      get; set;
    }

    public string DocumentTypeName {
      get; set;
    }

    public string Description {
      get; set;
    }

    public string Type {
      get; set;
    }

  }

我的示例窗口的代码隐藏:

public partial class Window1 : INotifyPropertyChanged {

    public Window1() {
      InitializeComponent();
      this._docs.Add(new Document { Name = "Doc1", Type = "docx", Description = "Important Doc", DocumentTypeName = "Word-Document" });
      this._docs.Add(new Document { Name = "Doc2", Type = "xlsx", Description = "Important Calculation", DocumentTypeName = "Excel-Document" });
      this._docs.Add(new Document { Name = "Doc3", Type = "pdf", Description = "Important Contract", DocumentTypeName = "Pdf-Document" });
      this.DataContext = this;


    }

    public Document SelectedDocument {
      get {
        return this._selectedDocument;
      }
      set {
        if (Equals(value, this._selectedDocument))
          return;
        this._selectedDocument = value;
        this.SubDocuments.Clear();
        this.SubDocuments.Add(value);
        this.OnPropertyChanged();
      }
    }

    public ObservableCollection<Document> SubDocuments
    {
      get { return this._subDocuments; }
      set
      {
        if (Equals(value, this._subDocuments)) return;
        this._subDocuments = value;
        this.OnPropertyChanged();
      }
    }

    private readonly ObservableCollection<Document> _docs = new ObservableCollection<Document>();
    private Document _selectedDocument;
    private ObservableCollection<Document> _subDocuments = new ObservableCollection<Document>();
    public ObservableCollection<Document> Documents => this._docs;

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }


  }

<强>封闭

此代码段应该为您提供一个想法,如何完成。它肯定不同于您的实际对象和实现。但既然你说你只需要朝着正确的方向推进,那么这可能会给你一个Jumpstart。

注意

我已经使用Code-Behind做了这个,并且模型没有实现INotifyPropertyChanged,因为在这个例子中它并不重要。

希望这有帮助。