WPF 将窗口标题绑定到 ViewModel 属性
Posted
技术标签:
【中文标题】WPF 将窗口标题绑定到 ViewModel 属性【英文标题】:WPF Bind Window Title to ViewModel Property 【发布时间】:2013-06-05 16:30:00 【问题描述】:我正在尝试将 Window Title 绑定到具有 Title 属性的 ViewModel。下面是 MainWindow XAML:
<Window x:Class="MyProject.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel"
Title="Binding Path=Title" Height="350" Width="525" DataContext="Binding Source=StaticResource mainWindowViewModel">
<Window.Resources>
<vm:MainWindow x:Key="mainWindowViewModel"/>
</Window.Resources>
...
</Window>
当我尝试运行它时,我得到以下异常“在 'System.Windows.StaticResourceExtension' 上提供值引发异常。行号和位置指向 DataContext 属性,内部异常状态为“找不到资源命名为 mainWindowViewModel。
下面是视图模型的代码:
namespace MyProject.ViewModel
public class MainWindow : INotifyPropertyChanged
#region Fields
private const string TitlebarPrefixString = "My Project";
private string title = TitlebarPrefixString;
public string Title
get
return this.title;
// End getter
set
this.title = value;
OnPropertyChanged("Title");
// End setter
// End property
protected virtual void OnPropertyChanged(string propertyName)
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
// End if
// End method
public event PropertyChangedEventHandler PropertyChanged;
// End class
// End namespace
我的理论是在尝试将标题绑定到属性之后加载资源。抛出异常时,Window 的 Resources 属性为空。
是唯一的解决方案是在后面的代码中设置 DataContext 吗?我可以让它工作,但我更愿意将它保存在 XAML 中。
【问题讨论】:
如果适用,您始终可以将您的 VM 资源移动到 app.xaml。在旁注中,请将 VM 类命名为SomethingViewModel
,而不仅仅是与 View 相同的名称,并使用命名空间来区分类。这真的很奇怪和怪异
Josh Smith 有一个这样的例子,我会看看我能不能找到它,基本上当在 XAML 中应用数据模板时,标题也被应用了..
【参考方案1】:
您可以尝试使用属性元素语法设置DataContext
:
<Window x:Class="MyProject.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel"
Title="Binding Path=Title" Height="350" Width="525">
<Window.Resources>
<vm:MainWindow x:Key="mainWindowViewModel"/>
</Window.Resources>
<Window.DataContext>
<StaticResourceExtension ResourceKey="mainWindowViewModel"/>
</Window.DataContext>
这应该可以工作,因为 xaml 解析器将在设置资源字典后执行 StaticResourceExtension
。
但我认为直接设置 DataContext 而不将其声明为资源可能更好:
<Window x:Class="MyProject.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MyProject.ViewModel;assembly=MyProject.ViewModel"
Title="Binding Path=Title" Height="350" Width="525">
<Window.DataContext>
<vm:MainWindow x:Key="mainWindowViewModel"/>
</Window.DataContext>
【讨论】:
您的第一个建议引发了同样的异常。有趣的是,当我使用 Break 时,Window 会在 Locals 视图中显示资源。第二个建议给出了三个编译时错误:““Key”属性只能用于 IDictionary 中包含的元素”; “Key 属性只能用于 IDictionary 类型属性中包含的标记”和“Key 属性只能用于字典中包含的标记(例如 ResourceDictionary” @Tim 我在 ResourceKey="mainWindowModel".. 中犯了一个错误。它应该声明 ResourceKey="mainWindowViewModel" 。如果您只是复制粘贴,请尝试更正它。但我不太确定这一点,我想一旦我让它像那样工作。 修复了它,这真是个好消息。我正在重新审视这个问题,因为我在引用以编程方式声明的视图模型时遇到了困难,因此再次将其设为纯 XAML 可能会帮助我解决其他问题。 @jure 你的建议帮助我解决了一个相关的问题。我想将窗口标题设置为带有路径和转换器的绑定。我在<Window.Resources>
中定义了转换器,但是在<Window>
中设置绑定会引发异常,因为它还没有访问<Window.Resources>
的权限。按照您建议的方式设置窗口标题是一种简单的解决方法。谢谢。【参考方案2】:
有点晚了,但我正在使用一个简单而完美的解决方案,以防人们仍在寻找可能性:
<Window x:Class="Project.MainWindow"
Title="Binding DataContext.ApplicationTitle, ElementName=TheMainView">
<views:MainView x:Name="TheMainView"/>
</Window>
很简单,只需向您的 MainViewModel 添加一个属性,即 MainView 的 DataContext,如下所示:
public string ApplicationTitle
get
var text = "Application Name";
if (!string.IsNullOrEmpty(_currentFileLoaded))
text += $" (_currentFileLoaded)";
return text;
希望对你有帮助..
【讨论】:
以上是关于WPF 将窗口标题绑定到 ViewModel 属性的主要内容,如果未能解决你的问题,请参考以下文章
将 WPF xaml 绑定到 ViewModel 而不构造它