最后一个TreeViewItem数据源更改后的仅触发事件

时间:2018-09-21 19:21:30

标签: c# wpf mvvm event-handling treeview

我的View中有一个TreeView,它绑定到ViewModel中的根<?php error_reporting(0); $salt = "eCwWELxi"; # salt value need to be picked from your database $amount = $_POST["amount"]; # amount need to be picked up from your database $reverseHash = generateReverseHash(); if ($_POST["hash"] == $reverseHash) { # transaction is successful # do the required javascript task echo("Transaction Success & Verified"); AndroidSuccess($_POST["amount"]); } else{ # transaction is tempered # handle it as required echo("<br>"); echo "\nInvalid transaction"; } # For Android Success function AndroidSuccess($input) { echo '<script type="text/javascript">'; echo 'PayU.onSuccess("Amount =" +'.$_POST["amount"].')'; echo "</script>"; } # Function to generate reverse hash function generateReverseHash() { global $salt; global $amount; if ($_POST["additional_charges"] != null) { $reversehash_string = $_POST["additional_charges"] . "|" . $salt . "|" . $_POST["status"] . "||||||" . $_POST["udf5"] . "|" . $_POST["udf4"] . "|" . $_POST["udf3"] . "|" . $_POST["udf2"] . "|" . $_POST["udf1"] . "|" . $_POST["email"] . "|" . $_POST["firstname"] . "|" . $_POST["productinfo"] . "|" . $amount . "|" . $_POST["txnid"] . "|" . $_POST["key"] ; } else{ $reversehash_string = $salt . "|" . $_POST["status"] . "||||||" . $_POST["udf5"] . "|" . $_POST["udf4"] . "|" . $_POST["udf3"] . "|" . $_POST["udf2"] . "|" . $_POST["udf1"] . "|" . $_POST["email"] . "|" . $_POST["firstname"] . "|" . $_POST["productinfo"] . "|" . $amount . "|" . $_POST["txnid"] . "|" . $_POST["key"] ; } // echo($reversehash_string); $reverseHash = strtolower(hash("sha512", $reversehash_string)); return $reverseHash; } 列表中。那些根Node可以有子Node。所有节点都具有相同的类型,并具有属性Nodes,该属性绑定到相应IsSelected中包含的IsChecked的{​​{1}}的{​​{1}}依赖项属性。 CheckBox已将TreeViewItem设置为CheckBox

IsThreeState

false是实现public class Node : PropertyChangedBase, INode { private bool? _isSelected; private IList<INode> _nodes; private INode _parent; public Node() { } public bool? IsSelected { get { return _isSelected; } set { if (_SetField(ref _isSelected, value)) { _OnIsSelectedChanged(); } } } public IList<INode> Nodes { get { return _nodes; } set { _SetField(ref _nodes, value); } } public INode Parent { get { return _parent; } set { _SetField(ref _parent, value); } } private void _OnIsSelectedChanged() { if (IsSelected.HasValue) { if (IsSelected.Value) { if (Parent != null) { // Set IsSelected on all parenting nodes to: // - true, if all of their immediate child packages have been selected // - null, else } if (Nodes != null && Nodes.Count > 0) { // Prevent running this method again by circumventing setting the property _SetField(ref _isSelected, null); } } else { if (Parent != null) { // Set IsSelected of the parent to null } if (Nodes != null) { // Set IsSelected = false on all child nodes } } } else if (Parent != null) { // Set IsSelected on all parenting nodes to: // - true, if all of their immediate child packages have been selected // - null, else } } } 的基类。它是在this SO answer之后设计的。如果设置值实际发生更改,则PropertyChangedBase返回INotifyPropertyChanged并通知属性更改。

如果用户单击CheckBox,则所做的更改还将传播父节点的(直到根节点)_SetField(ref object, object)属性,也传播到子节点的true属性。所有属性的传播完成后,我要触发一个事件。但是仅当没有其他节点将被更改时。然后,我想在ViewModel中做一些事情,这会花费一些时间,因此如果事件随每个更改的属性一起触发,这将是性能下降的原因。

该行为应为以下情况:

  • 如果节点的IsSelected设置为IsSelectedIsSelected,则如果不是节点的所有同级节点{,则父节点的true设置为null。将{1}}设置为IsSelectednull(然后将其传播到树上)。
  • 如果节点的IsSelected设置为truenull,则如果节点的所有兄弟姐妹的{{ 1}}设置为IsSelectedtrue(然后传播到树上)。
  • 如果节点的null设置为IsSelected,则其所有直接子节点的true也都设置为IsSelected(然后传播到树上)。
  • 设置为true的节点意味着并非所有其直接子节点都已被选择。

那么,只有在更改了最后一个节点之后,如何才能实现触发PropertyChanged事件(或我要实现的另一个事件)?

1 个答案:

答案 0 :(得分:1)

我最终做了Alexandru的建议。

我介绍了两个事件IsSelectedChangedPropagationStartedIsSelectedChangedPropagationCompleted,第一个在处理选择之前引发,第二个在完成时引发。该类现在看起来与此类似:

public class Node : PropertyChangedBase, INode
{
    // #### Attributes
    private bool? _isSelected;
    private IList<INode> _nodes;
    private INode _parent;

    // #### Constructor
    public Node()
    { }

    // #### Properties
    public bool? IsSelected
    {
        get { return _isSelected; }
        set
        {
            if (_SetField(ref _isSelected, value))
            {
                _OnIsSelectedChanged();
            }
        }
    }
    public IList<INode> Nodes
    {
        get { return _nodes; }
        set { _SetField(ref _nodes, value); }
    }
    public INode Parent
    {
        get { return _parent; }
        set { _SetField(ref _parent, value); }
    }

    // #### Events
    public event EventHandler IsSelectedChangedPropagationStarted;
    public event EventHandler IsSelectedChangedPropagationCompleted;

    // #### Instance Methods
    private void _OnIsSelectedChanged()
    {
        IsSelectedChangedPropagationStarted?.Invoke(this, EventArgs.Empty);

        if (IsSelected.HasValue)
        {
            if (IsSelected.Value)
            {
                RecursivelySetAllParents();

                if (Nodes != null && Nodes.Count > 0)
                {
                    // Prevent running this method again by circumventing setting the property
                    _SetField(ref _isSelected, null);
                }
            }
            else
            {
                if (Parent != null)
                {
                    // Set IsSelected of the parent to null
                }

                RecursivelySetAllChildren();
            }
        }
        else if (Parent != null)
        {
            // Set IsSelected on all parenting nodes to:
            //  - true, if all of their immediate child packages have been selected
            //  - null, else
        }

        IsSelectedChangedPropagationCompleted?.Invoke(this, EventArgs.Empty);
    }
}

通过实现自定义EventArgs,我还可以告诉侦听器是否有任何更改,以便他们可以采取相应的行动。