我从MyModernWindow
继承了一个类Window
,并添加了一个名为MyTitleLinks
的属性和依赖项属性。类型为MyLinkCollection : ObservableCollection<MyLink>
。在XAML中,我正在尝试定义MyTitleLinks
,并将MyLink.Command
属性绑定到Window的ViewModel中的属性。
我尝试过多种绑定方式,包括FindAncestor和ElementName,而且我一直都不成功。
如果使用{Binding AboutCommand}
或{Binding DataContext.AboutCommand, ElementName=mainWindow}
,我会在输出中收到此错误:
无法为目标找到管理FrameworkElement或FrameworkContentElement 元件。 BindingExpression:路径= AboutCommand;的DataItem = NULL;目标 元素是'MylLink'(HashCode = 30245787);目标属性是'命令' (输入'ICommand')
如果使用{Binding DataContext.AboutCommand, RelativeSource={RelativeSource AncestorType={x:Type local:MyModernWindow}}}
,
找不到引用'RelativeSource的绑定源 FindAncestor, AncestorType = 'My.Namespace.MyModernWindow', AncestorLevel = '1'”。 BindingExpression:路径= DataContext.AboutCommand; 的DataItem = NULL; target元素是'MyLink'(HashCode = 35075009);目标 属性是'Command'(类型'ICommand')
MainWindow.xaml
<local:MyModernWindow x:Class="My.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:My.Controls"
IsTitleVisible="True"
Style="{StaticResource MyModernWindow}"
Title="My Window"
WindowStartupLocation="CenterScreen">
<local:MyModernWindow.MyTitleLinks>
<local:MyLink DisplayName="Support" Source="https://www.google.com/support/" />
<local:MyLink DisplayName="About" Command="{Binding AboutCommand}" />
</local:MyModernWindow.MyTitleLinks>
</local:MyModernWindow>
MainWindow.xaml.cs
public partial class MainWindow : MyModernWindow
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
MyLinkCollection类
public class MyLinkCollection : ObservableCollection<MyLink>
{
}
MyLink课程
public class MyLink : DependencyObject
{
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(MyLink));
public static readonly DependencyProperty DisplayNameProperty = DependencyProperty.Register(nameof(DisplayName), typeof(string), typeof(MyLink));
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(nameof(Source), typeof(Uri), typeof(MyLink));
public Uri Source
{
get { return (Uri)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public string DisplayName
{
get { return (string)GetValue(DisplayNameProperty); }
set { SetValue(DisplayNameProperty, value); }
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public MyLink()
{
SetCurrentValue(VisibilityProperty, Visibility.Visible);
}
}
视图模型
public class MainWindowViewModel
{
public ICommand AboutCommand { get; private set; }
public MainWindowViewModel()
{
this.AboutCommand = new RelayCommand(OpenAboutWindow);
}
private void OpenAboutWindow(object o)
{
ModernDialog.ShowMessage("About Screen", "About", MessageBoxButton.OK);
}
}
我错过了什么?
答案 0 :(得分:1)
在this blog post的帮助下,我明白了。由于MyLink
和MyLinkCollection
不在可视化树中,因此我使用“代理元素”来提供上下文。
我给了我的窗口一个名字,创建了一个FrameworkElement
,然后创建了一个隐藏的ContentControl
。这就是我所需要的一切。
这是有效的XAML:
<local:MyModernWindow x:Class="My.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:My.Controls"
x:Name="Window"
IsTitleVisible="True"
Style="{StaticResource MyModernWindow}"
Title="My Window"
WindowStartupLocation="CenterScreen">
<local:MyModernWindow.Resources>
<FrameworkElement x:Key="ProxyElement" DataContext="{Binding DataContext, ElementName=Window}" />
</local:MyModernWindow.Resources>
<ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"/>
<local:MyModernWindow.MyTitleLinks>
<local:MyLink DisplayName="Support" Source="{Binding DataContext.SupportSource, Source={StaticResource ProxyElement}}" />
<local:MyLink DisplayName="About" Command="{Binding DataContext.AboutCommand, Source={StaticResource ProxyElement}}" />
</local:MyModernWindow.MyTitleLinks>
</local:MyModernWindow>
答案 1 :(得分:0)
出现此问题的原因是,DataContext没有从集合或MyLink项继承。
要让WPF无需代理元素即可自动为您管理继承,您需要在树的每一步中添加“ Freezable”,如下所示:
public class MyLinkCollection : FreezableCollection<MyLink>
{
}
和
public class MyLink : Freezable
{
// class body
}
Xaml Behaviors Wpf(Microsoft发布的项目)使用相同的方法在Xaml定义的集合内传播DataContext,而无需其他代理