【发布时间】:2014-08-06 20:53:46
【问题描述】:
我有一个视图模型如下:
public class SolutionViewModel : TreeViewItemViewModel {
public ObservableCollection<TreeViewItemViewModel> Children {
get { return mChildItems; }
}
public bool IsExpanded {
get { return mIsExpanded; }
set {
if (value != mIsExpanded) {
mIsExpanded = value;
OnPropertyChanged("IsExpanded");
}
if (mIsExpanded && mParentItem != null)
mParentItem.IsExpanded = true;
if (this.HasDummyChild) {
Children.Remove(EmptyItem);
LoadChildren();
}
}
}
public bool IsSelected {
get { return mIsSelected; }
set {
if (value != mIsSelected) {
mIsSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
protected override void LoadChildren() {
var subFolders = default(ReadOnlyCollection<Folder>);
if (!GetSubFolders(mSolution.Folder.Name, out subFolders)) {
subFolders = new ReadOnlyCollection<Folder>(new List<Folder>());
}
foreach (var folder in subFolders) {
Children.Add(new SolutionItemViewModel(this, folder));
}
}
public string SolutionName {
get { return mSolution.Name; }
}
}
TreeView 的 .Xaml 如下:
<TreeView Name="SolutionTree" ItemsSource="{Binding SolutionViewModel}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type localmodels:SolutionViewModel}"
ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="3,0" Source="..\Resources\Folder_25x25.png" />
<TextBlock Text="{Binding SolutionName}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
从SolutionExplorer中选择文件后:
public void SetBindingContext(SolutionViewModel SolutionViewModel) {
SolutionTree.DataContext = SolutionViewModel;
}
这是一种延迟加载模型,因此当项展开时,子项会被加载。
问题是我什至没有将解决方案名称作为顶级节点。
更新:
我验证该模型已分配SolutionName:
此外,根据@elgonzo 的评论,我编辑了.Xaml 以反映对ItemsSource 绑定的更改:
<TreeView Name="SolutionTree" ItemsSource="{Binding}">
<TreeView.ItemContainerStyle>
更新 2
在从OpenFileDialog 选择文件后引发事件处理程序时,将执行分配TreeView 数据上下文的代码:
private void OnOpenFile(string FilePath) {
mSolutionManager = SolutionManager.Load(FilePath);
mSolutionViewModel = new SolutionViewModel(mSolutionManager.Solution);
mMainWindow.SolutionExplorer.SetBindingContext(mSolutionViewModel);
mSolutionViewModel.Refresh();
}
当我踏入Refresh() 方法时:
public void Refresh() {
OnPropertyChanged("SolutionName");
}
...我发现 PropertyChangedEventHandler 没有订阅者。
【问题讨论】:
-
您需要为您的 SolutionViewModel 类实现 INotifyPropertyChanged 接口,并在 SolutionName时触发 PropertyChanged 事件> 属性变化。我猜 TreeViewItemViewModel 也缺少 INotifyPropertyChanged 实现。此外,您的 TreeView 似乎缺少 TreeViewItemViewModel... 的 DataTemplate
-
TreeViewItemViewModel是一个抽象类,为INotifyPropertyChanged提供实现。当SolutionViewModel被分配为树视图数据上下文时,SoltuionName 已被分配并且此后不会更改。我更新了问题以反映继承自 TreeViewItemViewModel 的继承链。 -
好的。只是解决方案名称没有显示。属性 SolutionViewModel(在 ItemsSource 绑定中使用)未正确设置(或未触发 PropertyChanged 事件以防在属性接收其预期值之前建立绑定),或 SolutionName(因此 mSolution.Name)在建立数据绑定时为空。如果在数据绑定建立后设置了 SolutionName(即 mSolution.Name),除非您通过 PropertyChanged 事件通知它,否则绑定无法知道这一点。
-
如果您设置
SolutionTree.DataContext = SolutionViewModel;,那么数据绑定ItemsSource="{Binding SolutionViewModel}"将尝试绑定到属性DataContext.SolutionViewModel,这将等于SolutionViewModel.SolutionViewModel。我想你应该尝试ItemsSource="{Binding}"绑定到 SolutionViewModel(即 DataContext)。 -
我看到你在一小时前进行了编辑。看起来你没有注意到我最后的评论,关于尝试将 TreeView.ItemSource 设置为
ItemsSource="{Binding}"(有关详细信息,请参阅我之前的评论)。
标签: c# xaml data-binding treeview viewmodel