I want to create a reusable control that has a behavior attribute. As described in this blog
To bind data, data must be converted. Problem in; as StaticResourcehe can see only the top-level dictionary ( app), and dynamic resources do not work ("can only be used with the dependency property").
Simple (working) xaml (window):
<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>
applications:
<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>
And finally, the 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();
}
}
}
Now, as said, this "works." However, he does not do what I want: he clogs the top-level resource dictionary. I want to remove the resource from the application. and put it under the grid. (Or any panel that I use).
<Grid.Resources>
<local:SelectionConverter x:Key="SelectionConverter" />
</Grid.Resources>
EDIT: , ( Converter="{StaticResource SelectionConverter}")
" " System.Windows.StaticResourceExtension ", . " 13 " " 38".
:
"SelectionConverter". : .
.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>