簡體   English   中英

WPF 樹視圖和數據網格選擇已更改

[英]WPF treeview and datagrid selection changed

我正在使用TreeviewDataGrid處理這個 WPF 項目。

左側是一個樹狀結構,其中一些文檔顯示在數據網格的右側。 如果我們更改樹視圖中的選定項,則數據網格顯示應更改。 All Documents 應該顯示 all 等等。 有人可以指出我正確的方向嗎? 我在帶有一些視圖模型的 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>

在此處輸入圖片說明

由於默認的 TreeView 不支持 SelectedItem 上的綁定,因此您必須執行一個丑陋的解決方法。 對 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));
    }


  }

關閉

這個片段應該為您提供一個想法,它是如何完成的。 它肯定與您的實際對象和實現不同。 但既然你說你只需要朝着正確的方向推動,這可能會給你一個快速啟動。

筆記

我已經用代碼隱藏做了這個,模型沒有實現INotifyPropertyChanged因為在這個例子中它並不重要。

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM