ResourceDictionary中的交互触发器WPF [英] Interaction Triggers in Style in ResourceDictionary WPF
问题描述
我有一个 ComboBox
,我需要在我的应用程序中的几个地方使用,所以我设置 ComboBox
在
ResourceDictionary
,并将其用作我需要它的样式。
ComboBox
是:
< Style TargetType ={x:Type ComboBox}x:Key =ComboBoxBranch>
< Setter Property =ItemsSourceValue ={Binding Branches}>< / Setter>
< Setter Property =DisplayMemberPathValue =BranchName>< / Setter>
< Setter Property =SelectedItemValue ={Binding SelectedBranch}>< / Setter>
< / Style>
我在我的XAML中使用它:
< ComboBox Style ={StaticResource ComboBoxBranch}>
< i:Interaction.Triggers>
< i:EventTrigger EventName =SelectionChanged>
< i:InvokeCommandAction Command ={Binding SelectCustomerCommand}CommandParameter ={Binding SelectedBranch}>< / i:InvokeCommandAction>
< / i:EventTrigger>
< / i:Interaction.Triggers>
< / ComboBox>
我想将交互触发器代码移动到 ResourceDictionary
,所以我不需要写在所有的xamls。可能以某种方式?
据我所知, Interaction.Triggers
不能分别应用在Style中和ResourceDictionary中。但是你可以这样做,确定 ComboBox
作为一个资源与 x:Shared =False
ContentControl
如下:
< Window.Resources>
< ComboBox x:Key =MyComboBox
x:Shared =False
ItemsSource ={Binding Branches}
DisplayMemberPath =BranchName
SelectedItem ={Binding SelectedBranch}>
< i:Interaction.Triggers>
< i:EventTrigger EventName =SelectionChanged>
< i:InvokeCommandAction Command ={Binding SelectCustomerCommand}/>
< / i:EventTrigger>
< / i:Interaction.Triggers>
< / ComboBox>
< /Window.Resources>
< Grid>
&ContentControl Name =MyComboBox1
Width =100
Height =30
HorizontalAlignment =Left
Content ={StaticResource MyComboBox} />
< ContentControl Name =MyComboBox2
Width =100
Height =30
HorizontalAlignment =Right
Content = {StaticResource MyComboBox}/>
< / Grid>
当 x:Shared =True
默认情况下,一个样式是所有的共同 - 在这种情况下,系统发出重复的内容
。当 x:Shared =False
时创建每个元素的Style,当它请求时。引自 MSDN
:
设置为 false 时,修改WPF资源检索行为,对于每个请求,为属性资源创建一个
新实例
,而不是为所有请求共享相同的实例。
有关详情,请参阅:
编辑:替代解决方案
Here
,Mr.Vspivak发布了一个解决方案,允许您轻松地在样式中设置 Interaction.Triggers
。
示例:
MainWindow.xaml
p>
< Window x:Class =StylesInteractivity.MainWindow
xmlns =http://schemas.microsoft.com / winfx / 2006 / xaml / presentation
xmlns:x =http://schemas.microsoft.com/winfx/2006/xaml
xmlns:ie =clr-namespace:System.Windows .Interactivity; assembly = System.Windows.Interactivity
xmlns:Core =clr-namespace:Microsoft.Expression.Interactivity.Core; assembly = Microsoft.Expression.Interactions
xmlns:int =clr -namespace:System.Windows.Interactivity
xmlns:si =clr-namespace:StylesInteractivity
Title =MainWindowHeight =350Width =525>
< Window.Resources>
< si:ViewModel x:Key =Model/>
< /Window.Resources>
< grid>
< Grid.ColumnDefinitions>
< ColumnDefinition />
< ColumnDefinition />
< /Grid.ColumnDefinitions>
< TextBlock Grid.Column =1x:Name =_ tblock
Text =Default
HorizontalAlignment =Center
VerticalAlignment = Center
FontSize =24
FontWeight =Bold/>
< ListBox ItemsSource ={Binding Source = {StaticResource Model},Path = DataSource}
Grid.Column =0
HorizontalAlignment =Center
VerticalAlignment =Center>
< ListBox.ItemContainerStyle>
< Style TargetType =ListBoxItem>
< Setter Property =FontSizeValue =24/>
< Setter Property =FontWeightValue =Bold/>
< Setter Property =int:InteractivityItems.Template>
< Setter.Value>
< int:InteractivityTemplate>
< int:InteractivityItems>
< int:InteractivityItems.Behaviors>
< int:FlipOnHover />
< / int:InteractivityItems.Behaviors>
< int:InteractivityItems.Triggers>
< ie:EventTrigger EventName =MouseMove>
< Core:ChangePropertyAction PropertyName =Text
TargetObject ={Binding ElementName = _tblock}
Value ={Binding}/>
< / ie:EventTrigger>
< / int:InteractivityItems.Triggers>
< / int:InteractivityItems>
< / int:InteractivityTemplate>
< /Setter.Value>
< / Setter>
< / Style>
< /ListBox.ItemContainerStyle>
< / ListBox>
< / Grid>
< / Window>
InteractivityHelper.cs
///< summary>
///< see cref =FrameworkTemplate/>对于InteractivityElements实例
///< remarks>子类为向前兼容性,也许有一天< see cref =FrameworkTemplate/> < / remarks>
///< remarks>不会部分内部< / remarks>
///< / summary>
public class InteractivityTemplate:DataTemplate
{
}
///< summary>
///用于交互项的持有者
///< / summary>
public class InteractivityItems:FrameworkElement
{
private List< Behavior> _行为;
private List< TriggerBase> _triggers;
///< summary>
///触发器的存储
///< / summary>
public List< TriggerBase>触发器
{
get
{
if(_triggers == null)
_triggers = new List< TriggerBase>();
return _triggers;
}
}
///< summary>
///行为存储
///< / summary>
public List< Behavior>行为
{
get
{
if(_behaviors == null)
_behaviors = new List< Behavior>();
return _behaviors;
}
}
#region模板附加属性
public static InteractivityTemplate GetTemplate(DependencyObject obj)
{
return InteractivityTemplate)obj.GetValue(TemplateProperty);
}
public static void SetTemplate(DependencyObject obj,InteractivityTemplate value)
{
obj.SetValue(TemplateProperty,value);
}
public static readonly DependencyProperty TemplateProperty =
DependencyProperty.RegisterAttached(Template,
typeof(InteractivityTemplate),
typeof(InteractivityItems),
new PropertyMetadata(default(InteractivityTemplate),OnTemplateChanged));
private static void OnTemplateChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
InteractivityTemplate dt =(InteractivityTemplate)e.NewValue;
#if(!SILVERLIGHT)
dt.Seal();
#endif
InteractivityItems ih =(InteractivityItems)dt.LoadContent();
BehaviorCollection bc = Interaction.GetBehaviors(d);
TriggerCollection tc = Interaction.GetTriggers(d);
foreach(ih.Behaviors中的行为行为)
bc.Add(behavior);
foreach(ih.Triggers中的TriggerBase触发器)
tc.Add(trigger);
}
#endregion
}
code> FlipOnHover.cs
public class FlipOnHover:Behavior< FrameworkElement>
{
protected override void OnAttached()
{
AssociatedObject.MouseEnter + = AssociatedObject_MouseEnter;
AssociatedObject.MouseLeave + = AssociatedObject_MouseLeave;
Transform t = AssociatedObject.RenderTransform;
AssociatedObject.RenderTransform = new TransformGroup();
((TransformGroup)AssociatedObject.RenderTransform).Children.Add(t);
((TransformGroup)AssociatedObject.RenderTransform).Children.Add(new ScaleTransform());
base.OnAttached();
}
void AssociatedObject_MouseLeave(object sender,System.Windows.Input.MouseEventArgs e)
{
((ScaleTransform)((TransformGroup)AssociatedObject.RenderTransform)。儿童[1])。
}
void AssociatedObject_MouseEnter(object sender,System.Windows.Input.MouseEventArgs e)
{
((ScaleTransform)((TransformGroup)AssociatedObject.RenderTransform)。 Children [1])。CenterX = AssociatedObject.ActualWidth / 2;
((ScaleTransform)((TransformGroup)AssociatedObject.RenderTransform).Children [1]。CenterY = AssociatedObject.ActualHeight / 2;
((ScaleTransform)((TransformGroup)AssociatedObject.RenderTransform).Children [1])ScaleY = -1;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseEnter - = AssociatedObject_MouseEnter;
AssociatedObject.MouseLeave - = AssociatedObject_MouseLeave;
}
}
ViewModel.cs
public class ViewModel
{
private ObservableCollection< String> _dataSource = new ObservableCollection< string>();
public ViewModel()
{
_dataSource.Add(Cat);
_dataSource.Add(Dog);
_dataSource.Add(Mouse);
_dataSource.Add(Owl);
_dataSource.Add(Rabbit);
}
public IEnumerable< string> DataSource
{
get {return _dataSource; }
}
}
有关详细信息, p>
在WPF / Silverlight样式中使用交互行为和操作
I have a ComboBox
which I need to use in several places in my application, so I set most of the properties of that ComboBox
in ResourceDictionary
and use that as a Style where ever I need it.
Style for the ComboBox
is:
<Style TargetType="{x:Type ComboBox}" x:Key="ComboBoxBranch">
<Setter Property="ItemsSource" Value="{Binding Branches}"></Setter>
<Setter Property="DisplayMemberPath" Value="BranchName"></Setter>
<Setter Property="SelectedItem" Value="{Binding SelectedBranch}"></Setter>
</Style>
and I am using it like this in my XAML:
<ComboBox Style="{StaticResource ComboBoxBranch}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectCustomerCommand}" CommandParameter="{Binding SelectedBranch}" ></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
I want to move the interaction trigger code as well to ResourceDictionary
, so I don't need to write it in all my xamls. Is it possible somehow?
As far as I know, Interaction.Triggers
can not be applied in Style, respectively and in a ResourceDictionary. But you can do so, to determine the ComboBox
as a resource with x:Shared="False"
and reference it for ContentControl
like this:
<Window.Resources>
<ComboBox x:Key="MyComboBox"
x:Shared="False"
ItemsSource="{Binding Branches}"
DisplayMemberPath="BranchName"
SelectedItem="{Binding SelectedBranch}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectCustomerCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</Window.Resources>
<Grid>
<ContentControl Name="MyComboBox1"
Width="100"
Height="30"
HorizontalAlignment="Left"
Content="{StaticResource MyComboBox}" />
<ContentControl Name="MyComboBox2"
Width="100"
Height="30"
HorizontalAlignment="Right"
Content="{StaticResource MyComboBox}" />
</Grid>
When x:Shared="True"
by default then one Style is common to all - in this case, the system swears on the duplicate Content
. When x:Shared="False"
when is created Style for each element whenever it its request. Quote from MSDN
:
When set to false, modifies WPF resource-retrieval behavior so that requests for the attributed resource create a
new instance
for each request instead of sharing the same instance for all requests.
For more information, please see:
Edit: alternative solution
Here
, Mr.Vspivak published a solution that allows you easily set the Interaction.Triggers
in Style.
Example:
MainWindow.xaml
<Window x:Class="StylesInteractivity.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ie="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:Core="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
xmlns:int="clr-namespace:System.Windows.Interactivity"
xmlns:si="clr-namespace:StylesInteractivity"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<si:ViewModel x:Key="Model" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" x:Name="_tblock"
Text="Default"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="24"
FontWeight="Bold" />
<ListBox ItemsSource="{Binding Source={StaticResource Model}, Path=DataSource}"
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="int:InteractivityItems.Template">
<Setter.Value>
<int:InteractivityTemplate>
<int:InteractivityItems>
<int:InteractivityItems.Behaviors>
<int:FlipOnHover />
</int:InteractivityItems.Behaviors>
<int:InteractivityItems.Triggers>
<ie:EventTrigger EventName="MouseMove">
<Core:ChangePropertyAction PropertyName="Text"
TargetObject="{Binding ElementName=_tblock}"
Value="{Binding}" />
</ie:EventTrigger>
</int:InteractivityItems.Triggers>
</int:InteractivityItems>
</int:InteractivityTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</Window>
InteractivityHelper.cs
/// <summary>
/// <see cref="FrameworkTemplate"/> for InteractivityElements instance
/// <remarks>Subclassed for forward compatibility, perhaps one day <see cref="FrameworkTemplate"/> </remarks>
/// <remarks>will not be partially internal</remarks>
/// </summary>
public class InteractivityTemplate : DataTemplate
{
}
/// <summary>
/// Holder for interactivity entries
/// </summary>
public class InteractivityItems : FrameworkElement
{
private List<Behavior> _behaviors;
private List<TriggerBase> _triggers;
/// <summary>
/// Storage for triggers
/// </summary>
public List<TriggerBase> Triggers
{
get
{
if (_triggers == null)
_triggers = new List<TriggerBase>();
return _triggers;
}
}
/// <summary>
/// Storage for Behaviors
/// </summary>
public List<Behavior> Behaviors
{
get
{
if (_behaviors == null)
_behaviors = new List<Behavior>();
return _behaviors;
}
}
#region Template attached property
public static InteractivityTemplate GetTemplate(DependencyObject obj)
{
return (InteractivityTemplate)obj.GetValue(TemplateProperty);
}
public static void SetTemplate(DependencyObject obj, InteractivityTemplate value)
{
obj.SetValue(TemplateProperty, value);
}
public static readonly DependencyProperty TemplateProperty =
DependencyProperty.RegisterAttached("Template",
typeof(InteractivityTemplate),
typeof(InteractivityItems),
new PropertyMetadata(default(InteractivityTemplate), OnTemplateChanged));
private static void OnTemplateChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
InteractivityTemplate dt = (InteractivityTemplate)e.NewValue;
#if(!SILVERLIGHT)
dt.Seal();
#endif
InteractivityItems ih = (InteractivityItems)dt.LoadContent();
BehaviorCollection bc = Interaction.GetBehaviors(d);
TriggerCollection tc = Interaction.GetTriggers(d);
foreach (Behavior behavior in ih.Behaviors)
bc.Add(behavior);
foreach (TriggerBase trigger in ih.Triggers)
tc.Add(trigger);
}
#endregion
}
FlipOnHover.cs
public class FlipOnHover : Behavior<FrameworkElement>
{
protected override void OnAttached()
{
AssociatedObject.MouseEnter += AssociatedObject_MouseEnter;
AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;
Transform t = AssociatedObject.RenderTransform;
AssociatedObject.RenderTransform = new TransformGroup();
((TransformGroup)AssociatedObject.RenderTransform).Children.Add(t);
((TransformGroup)AssociatedObject.RenderTransform).Children.Add(new ScaleTransform());
base.OnAttached();
}
void AssociatedObject_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
((ScaleTransform)((TransformGroup)AssociatedObject.RenderTransform).Children[1]).ScaleY = 1;
}
void AssociatedObject_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
((ScaleTransform)((TransformGroup)AssociatedObject.RenderTransform).Children[1]).CenterX = AssociatedObject.ActualWidth / 2;
((ScaleTransform)((TransformGroup)AssociatedObject.RenderTransform).Children[1]).CenterY = AssociatedObject.ActualHeight / 2;
((ScaleTransform)((TransformGroup)AssociatedObject.RenderTransform).Children[1]).ScaleY=-1;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseEnter -= AssociatedObject_MouseEnter;
AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave;
}
}
ViewModel.cs
public class ViewModel
{
private ObservableCollection<String> _dataSource = new ObservableCollection<string>();
public ViewModel()
{
_dataSource.Add("Cat");
_dataSource.Add("Dog");
_dataSource.Add("Mouse");
_dataSource.Add("Owl");
_dataSource.Add("Rabbit");
}
public IEnumerable<string> DataSource
{
get { return _dataSource; }
}
}
For more info, see this link:
Using Interactivity Behaviors and Actions in WPF/Silverlight Styles
这篇关于ResourceDictionary中的交互触发器WPF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!