ResourceDictionary中的交互触发器WPF [英] Interaction Triggers in Style in ResourceDictionary WPF

查看:634
本文介绍了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
Horizo​​ntalAlignment =Left
Content ={StaticResource MyComboBox} />

< ContentControl Name =MyComboBox2
Width =100
Height =30
Horizo​​ntalAlignment =Right
Content = {StaticResource MyComboBox}/>
< / Grid>

x:Shared =True默认情况下,一个样式是所有的共同 - 在这种情况下,系统发出重复的内容。当 x:Shared =False时创建每个元素的Style,当它请求时。引自 MSDN


设置为 false 时,修改WPF资源检索行为,对于每个请求,为属性资源创建一个新实例,而不是为所有请求共享相同的实例。


有关详情,请参阅:



MSDN:x:共享属性



编辑:替代解决方案

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
Horizo​​ntalAlignment =Center
VerticalAlignment = Center
FontSize =24
FontWeight =Bold/>

< ListBox ItemsSource ={Binding Source = {StaticResource Model},Path = DataSource}
Grid.Column =0
Horizo​​ntalAlignment =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:

MSDN: x:Shared Attribute

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆