[英]WPF treeview and datagrid selection changed
我正在使用Treeview
和DataGrid
處理這個 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.