我希望创建一个“可重复使用”的控件,它具有行为属性。正如此博客中所描述的。
为了进行数据绑定,数据必须进行转换。问题在于; 作为StaticResource
,它只能看到顶层字典(app
),而动态资源不起作用(“只能与依赖属性一起使用”)。
以下是简单(有效的) xaml (窗口):
<Window x:Class="testit.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Rectangle x:Name="blah" Fill="Yellow" Stroke="Black" Width="100" Height="100">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}">
<i:InvokeCommandAction.CommandParameter>
<Binding Path="Name"
Converter="{StaticResource SelectionConverter}"
RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Rectangle}" />
</i:InvokeCommandAction.CommandParameter>
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<TextBlock x:Name="namefield" Text="{Binding Data}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>
</Window>
应用:
<Application x:Class="testit.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:testit"
StartupUri="MainWindow.xaml">
<Application.Resources>
<local:SelectionConverter x:Key="SelectionConverter" />
</Application.Resources>
</Application>
最后是视图模型:
using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Data;
namespace testit
{
class ViewModel : INotifyPropertyChanged
{
private string _data;
private readonly DelegateCommand<string> _mouseEnterCommand = null;
public ViewModel() {
_data = "hello ";
_mouseEnterCommand = new DelegateCommand<string>(
(s) => {
var a = s ?? "world ";
Data += s;
return;
});
}
public DelegateCommand<string> MouseEnterCommand => _mouseEnterCommand;
public string Data {
get { return _data; }
set {
if (value == _data) return;
_data = value;
OnPropertyChanged("Data");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class SelectionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if (value == null) return "";
char[] charArray = ((string)value).ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
}
现在,正如所说的,“这个工作”。然而,它并没有做我想要的事情:它混乱了顶级资源字典。我希望将资源从“app.”中移除,并将其放在Grid下面(或者任何我使用的面板下面)。
<Grid.Resources>
<local:SelectionConverter x:Key="SelectionConverter" />
</Grid.Resources>
编辑:如果我将上述行添加到窗口内的网格中,则编译时会抛出以下错误(该行和位置是指Converter =“{StaticResource SelectionConverter}”
):
"'System.Windows.StaticResourceExtension'上提供的值引发了异常。'行号'13'和行位置'38'。"
内部异常如下:
找不到名为'SelectionConverter'的资源。资源名称区分大小写。
为了清晰起见,这是修改后的window.xaml:
<Window x:Class="testit.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:local="clr-namespace:testit"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Rectangle x:Name="blah" Fill="Yellow" Stroke="Black" Width="100" Height="100">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}">
<i:InvokeCommandAction.CommandParameter>
<Binding Path="Name"
Converter="{StaticResource SelectionConverter}"
RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Rectangle}" />
</i:InvokeCommandAction.CommandParameter>
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<TextBlock x:Name="namefield" Text="{Binding Data}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Grid.Resources>
<local:SelectionConverter x:Key="SelectionConverter" />
</Grid.Resources>
</Grid>
</Window>
Grid.Resources
放在Grid的顶部,而不是底部。StaticResource
会在解析过程的早期解析资源。 - 15ee8f99-57ff-4f92-890c-b56153