我正在使用Treeview
和DataGrid
。
左侧是树形结构,其中一些文档显示在数据网格的右侧。 如果我们在树视图中更改所选项,则数据网格显示应该更改。 所有文件应显示所有等等。 有人能指出我正确的方向吗?我在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>
答案 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
,因为在这个例子中它并不重要。
希望这有帮助。