我希望创建一个"可重复使用的"具有行为属性的控制项。如上所述in this blog
对于数据绑定,必须转换数据。问题是;作为StaticResource
,它只能看到顶级字典(app
),而动态资源不起作用("只能与依赖属性"一起使用)。 / p>
简单(工作)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>
最后是viewmodel:
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();
}
}
}
现在如上所述,这&#34;工作&#34;。然而,它并没有按照我的意愿行事:它使顶级资源字典变得混乱。我希望从app中删除该资源。并把它放在网格下面。 (或者我使用的任何面板)。
<Grid.Resources>
<local:SelectionConverter x:Key="SelectionConverter" />
</Grid.Resources>
编辑:如果我将上面的行添加到窗口内的网格中,则编译时会抛出以下错误(行和位置参考Converter="{StaticResource SelectionConverter}"
)
&#34;&#39;为System.Windows.StaticResourceExtension&#39;提供价值。扔了一个 。例外&#39;行号&#39; 13&#39;和行位置&#39; 38&#39;。&#34;
内部异常:
无法找到名为&#39; SelectionConverter&#39;的资源。资源名称是 区分大小写。
为清楚起见,这是修改后的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>
答案 0 :(得分:2)
StaticResource
标记扩展程序会在调用ProvideValue
时立即解析资源:
Lookup behavior for that resource类似于加载时查找,它将从当前XAML页面的标记中查找以前加载的资源
如果<{1}}的内容<{1>} 之后<{1}},则Grid.Resources
的内容在Grid
的内容未被“先前加载”时解析。
所以把资源放在网格的顶部,所以在你使用之前定义了任何东西:
Grid
如果你能够使用<Grid>
<Grid.Resources>
<local:SelectionConverter x:Key="SelectionConverter" />
</Grid.Resources>
<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>
,你会没事的,但当然你不能,因为你发现的原因。