繁体   English   中英

复选框选中事件触发多次 wpf mvvm

[英]checkbox checked event trigger multiple time wpf mvvm

我在 DataGrid 中获得了复选框列,该列在特定行中填充实时下载百分比,由 caseRefNo 过滤。 我需要添加复选框更改事件以执行某些操作。 我使用InvokeCommandAction将操作添加到复选框。 我意识到当我第一次单击复选框时,没关系,只触发一次。 但是当我第二次点击同一个复选框时触发了两次。第三次点击同一个复选框,它触发了四次。 相当可怕,很难弄清楚。

这是我的视图模型代码

public class DataGridDownloadViewModel:BindableBase
    {
        public ObservableCollection<tblTransaction> TransList { get; private set; }
        public DispatcherTimer dispatchTimer = new DispatcherTimer();
        public CollectionView TransView { get; private set; }

        public DelegateCommand<object> CheckCommand { get; set; }

        private String _UpdatePer;
        public String UpdatePercentage
        {
            get { return _UpdatePer; }
            set { SetProperty(ref _UpdatePer, value); }
        }

        private string _caseId;
        public string CaseID
        {
            get { return _caseId; }
            set { SetProperty(ref _caseId, value); }
        }

        private string _isChecked;
        public string isChecked
        {
            get { return _isChecked; }
            set { SetProperty(ref _isChecked, value); }
        }

        private bool CanExecute(object args)
        {
            return true;
        }

        private void CheckBoxChecker(object args)
        {
            //Should Work Here
            // Totally not coming to this function
            CheckBox chk = (CheckBox)args;
            string thichintae = chk.Name.ToString();

            Console.WriteLine(thichintae);
        }      

        public DataGridDownloadViewModel(List<tblTransaction> model)
        {
            CheckCommand = new DelegateCommand<object>(CheckBoxChecker, CanExecute);

            dispatchTimer.Interval = TimeSpan.FromMilliseconds(3000); 
            dispatchTimer.Tick += dispatchTimer_Tick;
            BackGroundThread bgT = Application.Current.Resources["BackGroundThread"] as BackGroundThread;

            bgT.GetPercentChanged += (ss, ee) =>
            {
                UpdatePercentage = bgT.local_percentage.ToString();               
            };

            bgT.GetCaseID += (ss, ee) =>
            {
                CaseID = bgT.local_caseRef;
            };

            TransList =new ObservableCollection<tblTransaction>(model);
            TransView = GetTransCollectionView(TransList);
            TransView.Filter = OnFilterTrans;

            var tokenSource = new CancellationTokenSource();
            var token = tokenSource.Token;

            var cancellationTokenSource = new CancellationTokenSource();

            dispatchTimer.Start();

        }

        private void dispatchTimer_Tick(object sender, EventArgs e)
        {
            UpdateDataGrid();
        }       

        public void UpdateDataGrid()
        {           
                foreach (tblTransaction tran in TransList)
                {
                    if (tran.caseRefNo == CaseID)
                    {
                        tran.incValue = int.Parse(UpdatePercentage);

                    }
                    else
                    {
                        tran.incValue = tran.incValue;                      
                    }
                }

                TransView.Refresh();           
        }

        bool OnFilterTrans(object item)
        {
            var trans = (tblTransaction)item;
            return true;           
        }

        public CollectionView GetTransCollectionView(ObservableCollection<tblTransaction> tranList)
        {
            return (CollectionView)CollectionViewSource.GetDefaultView(tranList);
        }
    }

这是上述视图模型的 XAML。

<Window x:Class="EmployeeManager.View.DataGridDownload"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        Title="DataGridDownload" Height="600" Width="790">
    <Grid>
        <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding TransView}" AutoGenerateColumns="False" Margin="10,62,0,0" VerticalAlignment="Top" Height="497" Width="762">
            <DataGrid.Columns>
                <DataGridTextColumn Header="caseRefNo" Binding="{Binding caseRefNo}" />
                <DataGridTextColumn Header="subjMatr" Binding="{Binding subjMatr}" />
                <DataGridTextColumn Header="Download %" Binding="{Binding incValue}" />
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox  Name="abcdef"
                                Content="Please Select" IsChecked="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="Checked">
                                        <i:InvokeCommandAction CommandParameter="{Binding ElementName=abcdef}" Command="{Binding DataContext.CheckCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}" />
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </CheckBox>
                        </DataTemplate>                        
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Label Content="{Binding incValue,UpdateSourceTrigger=PropertyChanged}" Background="Red" Foreground="White" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Label Content="{Binding UpdatePercentage}" HorizontalAlignment="Left" Background="Blue" Foreground="White" Margin="10,10,0,0" VerticalAlignment="Top" Width="338" Height="30">

        </Label>
        <Button Content="Button" HorizontalAlignment="Left" Margin="672,20,0,0" VerticalAlignment="Top" Width="75"/>

    </Grid>
</Window>

这是我的模型

    public class tblTransaction
{
    public string caseRefNo { get;set;}
    public string subjMatr { get; set; }
    public int incValue { get; set; }
    public DateTime? longTime { get; set; }

    public bool IsSelected { get; set; }
}

这是我的表格的图片

在此处输入图像描述

是因为 DispatcherTimer 吗? 欢迎所有建议。

df

在此处输入图像描述

我想我在你之前的问题中留下了一条评论,说将你的收藏包装到 CollectionView 是很臭的。

无论如何, TransView.Refresh(); 导致您的代码出现问题。 TransView.Refresh 将为每个选中的复选框触发“选中”事件。 刷新基本上要求 wpf 引擎将所有数据重新填充到您的 CollectionView 中,然后每个选中的复选框将再次触发选中的事件。

尝试将 dispatchTimer.Interval 设置为更短的时间,例如 300。您应该能够看到复选框中的“tick”不断闪烁,因为 TransView.Refresh。

实际上,我不知道为什么不将 TransList 绑定到 DataGrid 并在 UpdateDataGrid 方法上调用 BeginInvoke。

为了演示 ObservableCollection 的工作原理,我使用 ObservableCollection 重新编写了部分代码。 至少让事情更好地符合 MVVM 模型。

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class MainViewModel : ViewModelBase
{
    public ObservableCollection<TblTransaction> TransList { get; private set; }
    public DispatcherTimer DispatchTimer = new DispatcherTimer();        

    public MainViewModel()
    {
        var model = new ObservableCollection<TblTransaction>();
        for (int i = 0; i < 5; i++)
        {
            model.Add(new TblTransaction { CaseRefNo = i.ToString(), IncValue = i, LongTime = DateTime.Now, SubjMatr = i.ToString() });
            if (i == 3)
                model[i].IsSelected = true;
        }               

        DispatchTimer.Interval = TimeSpan.FromMilliseconds(200); 
        DispatchTimer.Tick += dispatchTimer_Tick;

        TransList = model;

        DispatchTimer.Start();
    }

    private void dispatchTimer_Tick(object sender, EventArgs e)
    {
        UpdateDataGrid();
    }       

    public void UpdateDataGrid()
    {           
        var ran = new Random();
        foreach (var tran in TransList)
            tran.IncValue = ran.Next(0, 100);
    }        
}

public class TblTransaction : ViewModelBase
{
    private string caseRefNo;
    private string subjMatr;
    private int incValue;
    private DateTime? longTime;
    private bool isSelected;
    public DelegateCommand<object> CheckCommand { get; set; }

    public TblTransaction()
    {
        CheckCommand = new DelegateCommand<object>(CheckBoxChecker, (p) => true);
    }

    private void CheckBoxChecker(object args)
    {
        //Should Work Here
        // Totally not coming to this function
        //CheckBox chk = (CheckBox)args;
        //string thichintae = chk.Name;

        Console.WriteLine(args);
    }


    public string CaseRefNo
    {
        get { return caseRefNo; }
        set
        {
            caseRefNo = value;
            OnPropertyChanged();
        }
    }

    public string SubjMatr
    {
        get { return subjMatr; }
        set
        {
            subjMatr = value;
            OnPropertyChanged();
        }
    }

    public int IncValue
    {
        get { return incValue; }
        set
        {
            incValue = value;
            OnPropertyChanged();
        }
    }

    public DateTime? LongTime
    {
        get { return longTime; }
        set
        {
            longTime = value;
            OnPropertyChanged();
        }
    }

    public bool IsSelected
    {
        get { return isSelected; }
        set
        {
            isSelected = value;
            OnPropertyChanged();
        }
    }
}

<Window x:Class="WpfTestProj.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:local="clr-namespace:WpfTestProj"
    xmlns:interact="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    mc:Ignorable="d" 
    d:DataContext="{d:DesignInstance Type=local:MainViewModel, IsDesignTimeCreatable=False}"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <DataGrid HorizontalAlignment="Left" ItemsSource="{Binding TransList}" AutoGenerateColumns="False" Margin="10,62,0,0" VerticalAlignment="Top" Height="497" Width="762">
        <DataGrid.Columns>
            <DataGridTextColumn Header="caseRefNo" Binding="{Binding CaseRefNo}" />
            <DataGridTextColumn Header="subjMatr" Binding="{Binding SubjMatr}" />
            <DataGridTextColumn Header="Download %" Binding="{Binding IncValue}" />
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <CheckBox
                            Content="Please Select" IsChecked="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                            <interact:Interaction.Triggers>
                                <interact:EventTrigger EventName="Checked">
                                    <interact:InvokeCommandAction CommandParameter="{Binding Path=CaseRefNo}" Command="{Binding Path=CheckCommand}" />
                                </interact:EventTrigger>
                            </interact:Interaction.Triggers>
                        </CheckBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="{Binding IncValue, UpdateSourceTrigger=PropertyChanged}" Background="Red" Foreground="White" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

    <Button Content="Button" HorizontalAlignment="Left" Margin="672,20,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM