【问题标题】:Wpf TabControl Interaction.Trigger fires mores than onceWpf TabControl Interaction.Trigger 多次触发
【发布时间】:2015-09-10 12:45:13
【问题描述】:

Wpf-Tabcontrol 和带有 Interaction.Trgiggers 的 Dataemplate 出现意外行为。

首先我定义了一个“ViewModel”。很简单:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace WpfApplication3 {
    public class Vm:  INotifyPropertyChanged {


        public Vm() {
            this.CmdClick = new RelayCommand( p => this.ExecuteClick(), p => this.CanExecuteClick() ); 
        }


        private string myName;

        public string MyName {
            get { return myName; }
            set {
                if( myName != value ) {
                    myName = value;
                    if( this.PropertyChanged != null ) {
                        this.PropertyChanged( this, new PropertyChangedEventArgs( "MyName" ) );
                    }
                }
            }
        } 


        private RelayCommand cmdClick;
        public RelayCommand CmdClick {
            get { return cmdClick; }
            set { cmdClick = value; }
        }


        #region Command
        private bool CanExecuteClick() {
            return true;
        }

        public void ExecuteClick() {
            MessageBox.Show( "MyName is " + MyName );
        }
        #endregion


        public event PropertyChangedEventHandler  PropertyChanged;
    }
}

接下来,我定义一个数据模板:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:l="clr-namespace:WpfApplication3"
                    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
                    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <DataTemplate  DataType="{x:Type l:Vm}" x:Key="Vm">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <TextBox Text="{Binding Path=MyName}" Grid.Row="0"/>
            <i:Interaction.Triggers>
                <ei:KeyTrigger Key="F5" ActiveOnFocus="True" FiredOn="KeyUp"  >
                    <i:InvokeCommandAction Command="{Binding CmdClick}" />
                </ei:KeyTrigger>
            </i:Interaction.Triggers>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

I use the datatemplate on the mainform inside a TabControl:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:l="clr-namespace:WpfApplication3"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <TabControl>
        <TabItem Header="Tab1">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <ContentControl ContentTemplate="{StaticResource Vm}"  x:Name="vm11" Content="{Binding}" Grid.Row="0"/>
            </Grid>
        </TabItem>
        <TabItem Header="Tab2">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <ContentControl ContentTemplate="{StaticResource Vm}"  x:Name="vm21" Content="{Binding}" Grid.Row="0"/>
                <ContentControl ContentTemplate="{StaticResource Vm}"  x:Name="vm22" Content="{Binding}" Grid.Row="1"/> 
            </Grid>
        </TabItem>
    </TabControl>
</Window>

后面的代码很简单:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication3 {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            this.vm11.Content = vm1;

            this.vm21.Content = vm2;
            this.vm22.Content = vm3;
            this.vm1.MyName = "Name1";
            this.vm2.MyName = "Name2";
            this.vm3.MyName = "Name3";

        }

        Vm vm1 = new Vm();
        Vm vm2 = new Vm();
        Vm vm3 = new Vm();
    }    
}

当我运行程序时,我在第一个 TextBox 中单击,按 F5 和 MessageBox posup。好的。 我切换标签页,在第二个文本框内单击,按 F5 并再次出现消息框。好的。 我切换回第一个标签页,按 F5,MessageBox 出现两次。呃。怎么了。 我切换回第二个标签页,消息框再次出现两次。 切换到第一个标签页后,消息框现在会显示树形时间。以此类推。

就像,KeyUp-Event 是在内部分配的,当再次显示数据模板时,没有取消引用它。但是我能做什么?

【问题讨论】:

    标签: wpf datatemplate tabcontrol keyup


    【解决方案1】:

    我认为您需要更改此属性

    private RelayCommand cmdClick;
        public RelayCommand CmdClick {
            get { return cmdClick; }
            set { cmdClick = value; }
    

    到

    private RelayCommand cmdClick;
        public RelayCommand CmdClick {
            get { return cmdClick; }
            set { if(cmdClick == null)cmdClick = value;  }
    

    【讨论】:

    • 谢谢,但没用。
    • cmdClick 是从不分配的,所以对 KeyUp 没有反应
    • 对不起,我的意思是 if(cmdClick == null)cmdClick = value;我更新了我的答案
    猜你喜欢
    • 2015-08-17
    • 2014-09-29
    • 2014-08-20
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多