问:
How to change a property of parent-viewmodel
again I need your help.

I'm building a WPF app, where I have a MainViewModel for a page, that contents a treeview. This treeview is bound to a ProjectTreeViewModel, that is created by the MainViewModel.

Now my ProjectTreeViewModel catches a click-event (using a relay command), that tells it, which node was clicked.

I need this information inside my MainViewmodel. How do I transfer it there?

EDIT... a runnable example

some Data to show in the tree:

```<code>using WpfApp1.Models;

namespace WpfApp1.Dataprovider
{
  class PlcAddressData
  {
    public static PlcAddress GetPlcRootItems(string projectName)
    {
        if (string.IsNullOrWhiteSpace(projectName))
            projectName = "Projekt-Datenpunkte";

        return new PlcAddress
        {
            Name = projectName,
            NodeId = 0,
            Children =
            {
                new PlcAddress
                {
                    Name = "Allgemein",
                    Comment = "allgemeine Datenpunkte",
                    NodeId = 1,
                    ParentNodeId = 0
                },
                new PlcAddress
                {
                    Name = "Infrastruktur",
                    Comment = "interne Datenpunkte der Infrastruktur",
                    ParentNodeId = 0,
                    NodeId = 2
                },
                new PlcAddress
                {
                    Name = "lokale IOs",
                    Comment = "Datenpunkte der SPS-Baugruppe",
                    ParentNodeId = 0,
                    NodeId = 3,
                    Children =
                    {
                        new PlcAddress
                        {
                            Name = "IO 0",
                            Comment = "first Channel of Plc-IO-Card",
                            NodeId = 4,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 1",
                            Comment = "second Channel of Plc-IO-Card",
                            NodeId = 5,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 2",
                            Comment = "third Channel of Plc-IO-Card",
                            NodeId = 6,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 3",
                            Comment = "forth Channel of Plc-IO-Card",
                            NodeId = 7,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 4",
                            Comment = "fifth Channel of Plc-IO-Card",
                            NodeId = 8,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 5",
                            Comment = "sixth Channel of Plc-IO-Card",
                            NodeId = 9,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 6",
                            Comment = "seventh Channel of Plc-IO-Card",
                            NodeId = 10,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 7",
                            Comment = "eighth Channel of Plc-IO-Card",
                            NodeId = 11,
                            ParentNodeId = 3
                        }
                    }
                }
            }
        };
    }
  }
}
</code>```

The PlcAddress-model (data for treeview-item):

```<code>using System.Collections.Generic;

namespace WpfApp1.Models
{
  public class PlcAddress
  {
    private List<PlcAddress> _children = new List<PlcAddress>();
    public List<PlcAddress> Children
    {
        get { return _children; }
        set { _children = value; }
    }

    public int NodeId { get; set; }
    public int ParentNodeId { get; set; }
    public string Name { get; set; }
    public string Comment { get; set; }
  }
}
</code>```

A RelayCommand:

```<code>using System;
using System.Windows.Input;

namespace WpfApp1.ViewModels.Commands
{
  public class RelayCommand : ICommand
  {
    #region Fields
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;
    #endregion

    #region Constructors
    public RelayCommand(Action<object> execute) : this(execute, null){ }
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute ?? throw new ArgumentNullException("execute");
        _canExecute = canExecute;
    }
    #endregion

    #region ICommand Members
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
    }
    #endregion
  }
}
</code>```

The MainViewModel:

```<code>using WpfApp1.Models;

namespace WpfApp1.ViewModels
{
  public class MainViewModel : INotifyPropertyChanged
  {
    public MainViewModel()
    {
        LoadProjectTree();

    }
    private void LoadProjectTree()
    {
        PlcAddress RootItem = Dataprovider.PlcAddressData.GetPlcRootItems("Parent Node of Project");
        _projectTree = new ProjectTreeviewModel(RootItem);
        _projectTree.PropertyChanged += ProjectTreePropertyChanged;
    }
    private void ProjectTreePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        ProjectTreeviewModel selectedNode = (ProjectTreeviewModel)sender;
        System.Console.WriteLine("selectedNode changed:" + selectedNode.SelectedNode);
        SelectedNode = selectedNode.SelectedNode;
        //MessageBox.Show("Some Property changed");
    }

    #region Properties
    private string _selectedNode;
    public string SelectedNode {
        get { return _selectedNode; }
        set
        {
            _selectedNode = value;
            OnPropertyChanged("SelectedNode");
        }
    }
    private ProjectTreeviewModel _projectTree;
    public ProjectTreeviewModel ProjectTree
    {
        get { return _projectTree; }
    }
    #endregion

    #region Events
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
  }
}
</code>```

The PlcAddressViewModel to show as item in the tree

```<code>using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using WpfApp1.Models;

namespace WpfApp1.ViewModels
{
  public class PlcAddressViewModel : INotifyPropertyChanged
  {
    #region Data
    private Collection<PlcAddressViewModel> _children;
    readonly PlcAddressViewModel _parent;
    readonly PlcAddress _plcAddress;

    bool _isExpanded;
    bool _isSelected;
    #endregion Data

    #region Constructors
    public PlcAddressViewModel(PlcAddress plcAddress) : this(plcAddress, null)
    {
    }

    private PlcAddressViewModel(PlcAddress plcAddress, PlcAddressViewModel parent)
    {
        _parent = parent;
        _plcAddress = plcAddress;

        _children = new Collection<PlcAddressViewModel>(
            (from child in _plcAddress.Children
             select new PlcAddressViewModel(child, this))
             .ToList<PlcAddressViewModel>());
    }
    #endregion Constructors

    #region AddressProperties
    public Collection<PlcAddressViewModel> Children
    {
        get { return _children; }
        set { _children = value; }
    }
    public string Name
    {
        get { return _plcAddress.Name; }
    }
    public string Comment
    {
        get { return _plcAddress.Comment; }
    }
    #endregion AddressProperties

    #region Presentation Members

    #region IsExpanded
    public bool IsExpanded
    {
        get { return _isExpanded; }
        set
        {
            if (value != _isExpanded)
            {
                _isExpanded = value;
                this.OnPropertyChanged("IsExpanded");
            }

            // Expand all the way up to the root
            if (_isExpanded && _parent != null)
                _parent.IsExpanded = true;
        }
    }
    #endregion IsExpanded

    #region IsSelected
    public bool IsSelected
    {
        get
        {
            if (_isSelected)
            {
                //Console.WriteLine("Nodeselected: " + this._plcAddress.Name);
            }
            return this._isSelected;
        }
        set
        {
            if (value != _isSelected)
            {
                _isSelected = value;
                this.OnPropertyChanged("IsSelected");
            }
        }
    }
    #endregion IsSelected

    #region Parent
    public PlcAddressViewModel Parent
    {
        get { return _parent; }
    }
    #endregion Parent

    #endregion Presentation Members

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChanged Members
  }
}
</code>```

The ProjectTreeViewModel where the selectionchanged is recognized

```<code>using System;
using System.Collections.ObjectModel;
using WpfApp1.Models;
using WpfApp1.ViewModels.Commands;

namespace WpfApp1.ViewModels
{
  public class ProjectTreeviewModel : INotifyPropertyChanged
  {
    #region Data
    public RelayCommand TreeNodeSelected { get; private set; }
    readonly ReadOnlyCollection<PlcAddressViewModel> _rootNodes;
    readonly PlcAddressViewModel _rootAddress;
    #endregion Data

    #region Constructor
    public ProjectTreeviewModel(PlcAddress rootAddress)
    {
        _rootAddress = new PlcAddressViewModel(rootAddress);

        _rootNodes = new ReadOnlyCollection<PlcAddressViewModel>(
            new PlcAddressViewModel[]
            {
                _rootAddress
            });

        TreeNodeSelected = new RelayCommand(ExecuteTreeNodeSelected, canExecuteMethod);
    }
    #endregion Constructor

    #region Properties
    private string _selectedNode;
    public string SelectedNode
    {
        get { return _selectedNode; }
        set
        {
            _selectedNode = value;
            OnPropertyChanged("SelectedNode");
        }
    }
    #endregion

    #region RootNode
    public ReadOnlyCollection<PlcAddressViewModel> ProjectNode
    {
        get { return _rootNodes; }
    }
    #endregion RootNode

    #region Commands
    private bool canExecuteMethod(object parameter)
    {
        return true;
    }
    private void ExecuteTreeNodeSelected(object parameter)
    {
        PlcAddressViewModel selectedNode = (PlcAddressViewModel)parameter;
        Console.WriteLine("Found this node: " + selectedNode.Name);
        SelectedNode = selectedNode.Name;
    }
    #endregion Commands
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}
</code>```

last but not least, the MainWindow.xaml

```<code><Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp1"
    xmlns:viewmodels="clr-namespace:WpfApp1.ViewModels"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800"
    >

<DockPanel LastChildFill="True">
    <StackPanel Margin="5" Orientation="Horizontal">
        <TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left"
              x:Name="ProjectTree" Margin="0 0 2 0" Grid.Column="0">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectedItemChanged">
                    <i:InvokeCommandAction Command="{Binding TreeNodeSelected}"
                                       CommandParameter="{Binding ElementName=ProjectTree, Path=SelectedItem}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
                    <Setter Property="FontWeight" Value="Normal"/>
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="FontWeight" Value="Bold"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TreeView.ItemContainerStyle>

            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </StackPanel>
    <!-- following Texblock is bound to a MainViewModels property -->
    <TextBlock Text="{Binding SelectedNode}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</DockPanel>
</Window>
</code>```

... and its codebehind:

```<code>using System.Windows;
using WpfApp1.ViewModels;

namespace WpfApp1
{
  public partial class MainWindow : Window
  {
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainViewModel();
    }
  }
}
</code>```

...after some hours of experiments, I solved it. The solution is in the snippets above and I don't know if that is the best way. I did it the folling way:

The Command-method ExecuteTreeNodeSelected changes the public property SelectedNode. That fires a notification OnPropertyChanged("SelectedNode");.

When creating the Treeviewmodel, in MainViewModel, I added an eventlistener to the PropertyChanged-event of the TreeViewModel _projectTree.PropertyChanged += ProjectTreePropertyChanged;. This Event changes the SelectedNode-property of the MainViewModel, that notifies the UI.

Thanks for your patience

答:
This is the ViewModel base class that I use for hierarchical data to be displayed in a TreeView control.

```<code>/// <summary>
/// A base class for items that can be displayed in a TreeView or other hierarchical display
/// </summary>
public class perTreeViewItemViewModelBase : perViewModelBase
{
    // a dummy item used in lazy loading mode, ensuring that each node has at least one child so that the expand button is shown
    private static perTreeViewItemViewModelBase LazyLoadingChildIndicator { get; }
        = new perTreeViewItemViewModelBase { Caption = "Loading Data ..." };

    private bool InLazyLoadingMode { get; set; }
    private bool LazyLoadTriggered { get; set; }
    private bool LazyLoadCompleted { get; set; }
    private bool RequiresLazyLoad => InLazyLoadingMode && !LazyLoadTriggered;

    // Has Children been overridden (e.g. to point at some private internal collection)
    private bool LazyLoadChildrenOverridden => InLazyLoadingMode && !Equals(LazyLoadChildren, _childrenList);

    private readonly perObservableCollection<perTreeViewItemViewModelBase> _childrenList
        = new perObservableCollection<perTreeViewItemViewModelBase>();

    /// <summary>
    /// LazyLoadingChildIndicator ensures a visible expansion toggle button in lazy loading mode
    /// </summary>
    protected void SetLazyLoadingMode()
    {
        ClearChildren();
        _childrenList.Add(LazyLoadingChildIndicator);

        IsExpanded = false;
        InLazyLoadingMode = true;
        LazyLoadTriggered = false;
        LazyLoadCompleted = false;
    }

    private string _caption;

    public string Caption
    {
        get => _caption;
        set => Set(nameof(Caption), ref _caption, value);
    }

    public void ClearChildren()
    {
        _childrenList.Clear();
    }

    /// <summary>
    /// Add a new child item to this TreeView item
    /// </summary>
    /// <param name="child"></param>
    public void AddChild(perTreeViewItemViewModelBase child)
    {
        if (LazyLoadChildrenOverridden)
            throw new InvalidOperationException("Don't call AddChild for an item with LazyLoad mode set & LazyLoadChildren has been overridden");

        if (_childrenList.Any() && _childrenList.First() == LazyLoadingChildIndicator)
            _childrenList.Clear();

        _childrenList.Add(child);

        SetChildPropertiesFromParent(child);
    }

    protected void SetChildPropertiesFromParent(perTreeViewItemViewModelBase child)
    {
        child.Parent = this;

        // if this node is checked then all new children added are set checked
        if (IsChecked.GetValueOrDefault())
            child.SetIsCheckedIncludingChildren(true);

        ReCalculateNodeCheckState();
    }

    protected void ReCalculateNodeCheckState()
    {
        var item = this;

        while (item != null)
        {
            if (item.Children.Any() && !Equals(item.Children.FirstOrDefault(), LazyLoadingChildIndicator))
            {
                var hasIndeterminateChild = item.Children.Any(c => c.IsEnabled && !c.IsChecked.HasValue);

                if (hasIndeterminateChild)
                    item.SetIsCheckedThisItemOnly(null);
                else
                {
                    var hasSelectedChild = item.Children.Any(c => c.IsEnabled && c.IsChecked.GetValueOrDefault());
                    var hasUnselectedChild = item.Children.Any(c => c.IsEnabled && !c.IsChecked.GetValueOrDefault());

                    if (hasUnselectedChild && hasSelectedChild)
                        item.SetIsCheckedThisItemOnly(null);
                    else
                        item.SetIsCheckedThisItemOnly(hasSelectedChild);
                }
            }

            item = item.Parent;
        }
    }

    private void SetIsCheckedIncludingChildren(bool? value)
    {
        if (IsEnabled)
        {
            _isChecked = value;
            RaisePropertyChanged(nameof(IsChecked));

            foreach (var child in Children)
                if (child.IsEnabled)
                    child.SetIsCheckedIncludingChildren(value);
        }
    }

    private void SetIsCheckedThisItemOnly(bool? value)
    {
        _isChecked = value;
        RaisePropertyChanged(nameof(IsChecked));
    }

    /// <summary>
    /// Add multiple children to this TreeView item
    /// </summary>
    /// <param name="children"></param>
    public void AddChildren(IEnumerable<perTreeViewItemViewModelBase> children)
    {
        foreach (var child in children)
            AddChild(child);
    }

    /// <summary>
    /// Remove a child item from this TreeView item
    /// </summary>
    public void RemoveChild(perTreeViewItemViewModelBase child)
    {
        _childrenList.Remove(child);
        child.Parent = null;

        ReCalculateNodeCheckState();
    }

    public perTreeViewItemViewModelBase Parent { get; private set; }

    private bool? _isChecked = false;

    public bool? IsChecked
    {
        get => _isChecked;
        set
        {
            if (Set(nameof(IsChecked), ref _isChecked, value))
            {
                foreach (var child in Children)
                    if (child.IsEnabled)
                        child.SetIsCheckedIncludingChildren(value);

                Parent?.ReCalculateNodeCheckState();
            }
        }
    }

    private bool _isExpanded;

    public bool IsExpanded
    {
        get => _isExpanded;
        set
        {
            if (Set(nameof(IsExpanded), ref _isExpanded, value) && value && RequiresLazyLoad)
                TriggerLazyLoading();
        }
    }

    private bool _isEnabled = true;

    public bool IsEnabled
    {
        get => _isEnabled;
        set => Set(nameof(IsEnabled), ref _isEnabled, value);
    }

    public void TriggerLazyLoading()
    {
        var unused = DoLazyLoadAsync();
    }

    private async Task DoLazyLoadAsync()
    {
        if (LazyLoadTriggered)
            return;

        LazyLoadTriggered = true;

        var lazyChildrenResult = await LazyLoadFetchChildren()
            .EvaluateFunctionAsync()
            .ConfigureAwait(false);

        LazyLoadCompleted = true;

        if (lazyChildrenResult.IsCompletedOk)
        {
            var lazyChildren = lazyChildrenResult.Data;

            foreach (var child in lazyChildren)
                SetChildPropertiesFromParent(child);

            // If LazyLoadChildren has been overridden then just refresh the check state (using the new children)
            // and update the check state (in case any of the new children is already set as checked)
            if (LazyLoadChildrenOverridden)
                ReCalculateNodeCheckState();
            else
                AddChildren(lazyChildren); // otherwise add the new children to the base collection.
        }

        RefreshChildren();
    }

    /// <summary>
    /// Get the children for this node, in Lazy-Loading Mode
    /// </summary>
    /// <returns></returns>
    protected virtual Task<perTreeViewItemViewModelBase[]> LazyLoadFetchChildren()
    {
        return Task.FromResult(new perTreeViewItemViewModelBase[0]);
    }

    /// <summary>
    /// Update the Children property
    /// </summary>
    public void RefreshChildren()
    {
        RaisePropertyChanged(nameof(Children));
    }

    /// <summary>
    /// In LazyLoading Mode, the Children property can be set to something other than
    /// the base _childrenList collection - e.g as the union ot two internal collections
    /// </summary>
    public IEnumerable<perTreeViewItemViewModelBase> Children => LazyLoadCompleted
                                                                ? LazyLoadChildren
                                                                : _childrenList;

    /// <summary>
    /// How are the children held when in lazy loading mode.
    /// </summary>
    /// <remarks>
    /// Override this as required in descendent classes - e.g. if Children is formed from a union
    /// of multiple internal child item collections (of different types) which are populated in LazyLoadFetchChildren()
    /// </remarks>
    protected virtual IEnumerable<perTreeViewItemViewModelBase> LazyLoadChildren => _childrenList;

    private bool _isSelected;

    public bool IsSelected
    {
        get => _isSelected;
        set
        {
            // if unselecting we don't care about anything else other than simply updating the property
            if (!value)
            {
                Set(nameof(IsSelected), ref _isSelected, false);
                return;
            }

            // Build a priority queue of operations
            //
            // All operations relating to tree item expansion are added with priority = DispatcherPriority.ContextIdle, so that they are
            // sorted before any operations relating to selection (which have priority = DispatcherPriority.ApplicationIdle).
            // This ensures that the visual container for all items are created before any selection operation is carried out.
            //
            // First expand all ancestors of the selected item - those closest to the root first
            //
            // Expanding a node will scroll as many of its children as possible into view - see perTreeViewItemHelper, but these scrolling
            // operations will be added to the queue after all of the parent expansions.
            var ancestorsToExpand = new Stack<perTreeViewItemViewModelBase>();

            var parent = Parent;
            while (parent != null)
            {
                if (!parent.IsExpanded)
                    ancestorsToExpand.Push(parent);

                parent = parent.Parent;
            }

            while (ancestorsToExpand.Any())
            {
                var parentToExpand = ancestorsToExpand.Pop();
                perDispatcherHelper.AddToQueue(() => parentToExpand.IsExpanded = true, DispatcherPriority.ContextIdle);
            }

            // Set the item's selected state - use DispatcherPriority.ApplicationIdle so this operation is executed after all
            // expansion operations, no matter when they were added to the queue.
            //
            // Selecting a node will also scroll it into view - see perTreeViewItemHelper
            perDispatcherHelper.AddToQueue(() => Set(nameof(IsSelected), ref _isSelected, true), DispatcherPriority.ApplicationIdle);

            // note that by rule, a TreeView can only have one selected item, but this is handled automatically by
            // the control - we aren't required to manually unselect the previously selected item.

            // execute all of the queued operations in descending DispatcherPriority order (expansion before selection)
            var unused = perDispatcherHelper.ProcessQueueAsync();
        }
    }

    public override string ToString()
    {
        return Caption;
    }

    /// <summary>
    /// What's the total number of child nodes beneath this one
    /// </summary>
    public int ChildCount => Children.Count() + Children.Sum(c => c.ChildCount);
}
</code>```

Amongst other features, it includes a Parent property, so each item in the data structure knows its immediate ancestor.

Rather than using an event to handle an item being clicked, I've created a behaviour to add a bindable selected item property to a TreeView. This allows a change of selection to be detected for means other than a direct mouse click, such as the user pressing the arrow keys.

```<code>public class perTreeViewHelper : Behavior<TreeView>
{
    public object BoundSelectedItem
    {
        get => GetValue(BoundSelectedItemProperty);
        set => SetValue(BoundSelectedItemProperty, value);
    }

    public static readonly DependencyProperty BoundSelectedItemProperty =
        DependencyProperty.Register("BoundSelectedItem",
            typeof(object),
            typeof(perTreeViewHelper),
            new FrameworkPropertyMetadata(null,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                OnBoundSelectedItemChanged));

    private static void OnBoundSelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue is perTreeViewItemViewModelBase item)
            item.IsSelected = true;
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
        base.OnDetaching();
    }

    private void OnTreeViewSelectedItemChanged(object obj, RoutedPropertyChangedEventArgs<object> args)
    {
        BoundSelectedItem = args.NewValue;
    }
}
</code>```

More details on my blog post

Body:
again I need your help.

I'm building a WPF app, where I have a MainViewModel for a page, that contents a treeview. This treeview is bound to a ProjectTreeViewModel, that is created by the MainViewModel.

Now my ProjectTreeViewModel catches a click-event (using a relay command), that tells it, which node was clicked.

I need this information inside my MainViewmodel. How do I transfer it there?

EDIT... a runnable example

some Data to show in the tree:

using WpfApp1.Models;

namespace WpfApp1.Dataprovider
{
  class PlcAddressData
  {
    public static PlcAddress GetPlcRootItems(string projectName)
    {
        if (string.IsNullOrWhiteSpace(projectName))
            projectName = "Projekt-Datenpunkte";

        return new PlcAddress
        {
            Name = projectName,
            NodeId = 0,
            Children =
            {
                new PlcAddress
                {
                    Name = "Allgemein",
                    Comment = "allgemeine Datenpunkte",
                    NodeId = 1,
                    ParentNodeId = 0
                },
                new PlcAddress
                {
                    Name = "Infrastruktur",
                    Comment = "interne Datenpunkte der Infrastruktur",
                    ParentNodeId = 0,
                    NodeId = 2
                },
                new PlcAddress
                {
                    Name = "lokale IOs",
                    Comment = "Datenpunkte der SPS-Baugruppe",
                    ParentNodeId = 0,
                    NodeId = 3,
                    Children =
                    {
                        new PlcAddress
                        {
                            Name = "IO 0",
                            Comment = "first Channel of Plc-IO-Card",
                            NodeId = 4,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 1",
                            Comment = "second Channel of Plc-IO-Card",
                            NodeId = 5,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 2",
                            Comment = "third Channel of Plc-IO-Card",
                            NodeId = 6,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 3",
                            Comment = "forth Channel of Plc-IO-Card",
                            NodeId = 7,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 4",
                            Comment = "fifth Channel of Plc-IO-Card",
                            NodeId = 8,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 5",
                            Comment = "sixth Channel of Plc-IO-Card",
                            NodeId = 9,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 6",
                            Comment = "seventh Channel of Plc-IO-Card",
                            NodeId = 10,
                            ParentNodeId = 3
                        },
                        new PlcAddress
                        {
                            Name = "IO 7",
                            Comment = "eighth Channel of Plc-IO-Card",
                            NodeId = 11,
                            ParentNodeId = 3
                        }
                    }
                }
            }
        };
    }
  }
}

The PlcAddress-model (data for treeview-item):

using System.Collections.Generic;

namespace WpfApp1.Models
{
  public class PlcAddress
  {
    private List<PlcAddress> _children = new List<PlcAddress>();
    public List<PlcAddress> Children
    {
        get { return _children; }
        set { _children = value; }
    }

    public int NodeId { get; set; }
    public int ParentNodeId { get; set; }
    public string Name { get; set; }
    public string Comment { get; set; }
  }
}

A RelayCommand:

using System;
using System.Windows.Input;

namespace WpfApp1.ViewModels.Commands
{
  public class RelayCommand : ICommand
  {
    #region Fields
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;
    #endregion

    #region Constructors
    public RelayCommand(Action<object> execute) : this(execute, null){ }
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute ?? throw new ArgumentNullException("execute");
        _canExecute = canExecute;
    }
    #endregion

    #region ICommand Members
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
    }
    #endregion
  }
}

The MainViewModel:

using WpfApp1.Models;

namespace WpfApp1.ViewModels
{
  public class MainViewModel : INotifyPropertyChanged
  {
    public MainViewModel()
    {
        LoadProjectTree();

    }
    private void LoadProjectTree()
    {
        PlcAddress RootItem = Dataprovider.PlcAddressData.GetPlcRootItems("Parent Node of Project");
        _projectTree = new ProjectTreeviewModel(RootItem);
        _projectTree.PropertyChanged += ProjectTreePropertyChanged;
    }
    private void ProjectTreePropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        ProjectTreeviewModel selectedNode = (ProjectTreeviewModel)sender;
        System.Console.WriteLine("selectedNode changed:" + selectedNode.SelectedNode);
        SelectedNode = selectedNode.SelectedNode;
        //MessageBox.Show("Some Property changed");
    }

    #region Properties
    private string _selectedNode;
    public string SelectedNode {
        get { return _selectedNode; }
        set
        {
            _selectedNode = value;
            OnPropertyChanged("SelectedNode");
        }
    }
    private ProjectTreeviewModel _projectTree;
    public ProjectTreeviewModel ProjectTree
    {
        get { return _projectTree; }
    }
    #endregion

    #region Events
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
  }
}

The PlcAddressViewModel to show as item in the tree

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using WpfApp1.Models;

namespace WpfApp1.ViewModels
{
  public class PlcAddressViewModel : INotifyPropertyChanged
  {
    #region Data
    private Collection<PlcAddressViewModel> _children;
    readonly PlcAddressViewModel _parent;
    readonly PlcAddress _plcAddress;

    bool _isExpanded;
    bool _isSelected;
    #endregion Data

    #region Constructors
    public PlcAddressViewModel(PlcAddress plcAddress) : this(plcAddress, null)
    {
    }

    private PlcAddressViewModel(PlcAddress plcAddress, PlcAddressViewModel parent)
    {
        _parent = parent;
        _plcAddress = plcAddress;

        _children = new Collection<PlcAddressViewModel>(
            (from child in _plcAddress.Children
             select new PlcAddressViewModel(child, this))
             .ToList<PlcAddressViewModel>());
    }
    #endregion Constructors

    #region AddressProperties
    public Collection<PlcAddressViewModel> Children
    {
        get { return _children; }
        set { _children = value; }
    }
    public string Name
    {
        get { return _plcAddress.Name; }
    }
    public string Comment
    {
        get { return _plcAddress.Comment; }
    }
    #endregion AddressProperties

    #region Presentation Members

    #region IsExpanded
    public bool IsExpanded
    {
        get { return _isExpanded; }
        set
        {
            if (value != _isExpanded)
            {
                _isExpanded = value;
                this.OnPropertyChanged("IsExpanded");
            }

            // Expand all the way up to the root
            if (_isExpanded && _parent != null)
                _parent.IsExpanded = true;
        }
    }
    #endregion IsExpanded

    #region IsSelected
    public bool IsSelected
    {
        get
        {
            if (_isSelected)
            {
                //Console.WriteLine("Nodeselected: " + this._plcAddress.Name);
            }
            return this._isSelected;
        }
        set
        {
            if (value != _isSelected)
            {
                _isSelected = value;
                this.OnPropertyChanged("IsSelected");
            }
        }
    }
    #endregion IsSelected

    #region Parent
    public PlcAddressViewModel Parent
    {
        get { return _parent; }
    }
    #endregion Parent

    #endregion Presentation Members

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion INotifyPropertyChanged Members
  }
}

The ProjectTreeViewModel where the selectionchanged is recognized

using System;
using System.Collections.ObjectModel;
using WpfApp1.Models;
using WpfApp1.ViewModels.Commands;

namespace WpfApp1.ViewModels
{
  public class ProjectTreeviewModel : INotifyPropertyChanged
  {
    #region Data
    public RelayCommand TreeNodeSelected { get; private set; }
    readonly ReadOnlyCollection<PlcAddressViewModel> _rootNodes;
    readonly PlcAddressViewModel _rootAddress;
    #endregion Data

    #region Constructor
    public ProjectTreeviewModel(PlcAddress rootAddress)
    {
        _rootAddress = new PlcAddressViewModel(rootAddress);

        _rootNodes = new ReadOnlyCollection<PlcAddressViewModel>(
            new PlcAddressViewModel[]
            {
                _rootAddress
            });

        TreeNodeSelected = new RelayCommand(ExecuteTreeNodeSelected, canExecuteMethod);
    }
    #endregion Constructor

    #region Properties
    private string _selectedNode;
    public string SelectedNode
    {
        get { return _selectedNode; }
        set
        {
            _selectedNode = value;
            OnPropertyChanged("SelectedNode");
        }
    }
    #endregion

    #region RootNode
    public ReadOnlyCollection<PlcAddressViewModel> ProjectNode
    {
        get { return _rootNodes; }
    }
    #endregion RootNode

    #region Commands
    private bool canExecuteMethod(object parameter)
    {
        return true;
    }
    private void ExecuteTreeNodeSelected(object parameter)
    {
        PlcAddressViewModel selectedNode = (PlcAddressViewModel)parameter;
        Console.WriteLine("Found this node: " + selectedNode.Name);
        SelectedNode = selectedNode.Name;
    }
    #endregion Commands
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

last but not least, the MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp1"
    xmlns:viewmodels="clr-namespace:WpfApp1.ViewModels"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800"
    >

<DockPanel LastChildFill="True">
    <StackPanel Margin="5" Orientation="Horizontal">
        <TreeView DataContext="{Binding ProjectTree}" ItemsSource="{Binding ProjectNode}" DockPanel.Dock="Left"
              x:Name="ProjectTree" Margin="0 0 2 0" Grid.Column="0">

            <TreeView.ItemContainerStyle>

                </Style>
            </TreeView.ItemContainerStyle>

            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </StackPanel>

    <TextBlock Text="{Binding SelectedNode}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</DockPanel>
</Window>

... and its codebehind:

using System.Windows;
using WpfApp1.ViewModels;

namespace WpfApp1
{
  public partial class MainWindow : Window
  {
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainViewModel();
    }
  }
}

...after some hours of experiments, I solved it. The solution is in the snippets above and I don't know if that is the best way. I did it the folling way:

The Command-method ExecuteTreeNodeSelected changes the public property SelectedNode. That fires a notification OnPropertyChanged("SelectedNode");.

When creating the Treeviewmodel, in MainViewModel, I added an eventlistener to the PropertyChanged-event of the TreeViewModel _projectTree.PropertyChanged += ProjectTreePropertyChanged;. This Event changes the SelectedNode-property of the MainViewModel, that notifies the UI.

Thanks for your patience

Body:
This is the ViewModel base class that I use for hierarchical data to be displayed in a TreeView control.

/// <summary>
/// A base class for items that can be displayed in a TreeView or other hierarchical display
/// </summary>
public class perTreeViewItemViewModelBase : perViewModelBase
{
    // a dummy item used in lazy loading mode, ensuring that each node has at least one child so that the expand button is shown
    private static perTreeViewItemViewModelBase LazyLoadingChildIndicator { get; }
        = new perTreeViewItemViewModelBase { Caption = "Loading Data ..." };

    private bool InLazyLoadingMode { get; set; }
    private bool LazyLoadTriggered { get; set; }
    private bool LazyLoadCompleted { get; set; }
    private bool RequiresLazyLoad => InLazyLoadingMode && !LazyLoadTriggered;

    // Has Children been overridden (e.g. to point at some private internal collection)
    private bool LazyLoadChildrenOverridden => InLazyLoadingMode && !Equals(LazyLoadChildren, _childrenList);

    private readonly perObservableCollection<perTreeViewItemViewModelBase> _childrenList
        = new perObservableCollection<perTreeViewItemViewModelBase>();

    /// <summary>
    /// LazyLoadingChildIndicator ensures a visible expansion toggle button in lazy loading mode
    /// </summary>
    protected void SetLazyLoadingMode()
    {
        ClearChildren();
        _childrenList.Add(LazyLoadingChildIndicator);

        IsExpanded = false;
        InLazyLoadingMode = true;
        LazyLoadTriggered = false;
        LazyLoadCompleted = false;
    }

    private string _caption;

    public string Caption
    {
        get => _caption;
        set => Set(nameof(Caption), ref _caption, value);
    }

    public void ClearChildren()
    {
        _childrenList.Clear();
    }

    /// <summary>
    /// Add a new child item to this TreeView item
    /// </summary>
    /// <param name="child"></param>
    public void AddChild(perTreeViewItemViewModelBase child)
    {
        if (LazyLoadChildrenOverridden)
            throw new InvalidOperationException("Don't call AddChild for an item with LazyLoad mode set & LazyLoadChildren has been overridden");

        if (_childrenList.Any() && _childrenList.First() == LazyLoadingChildIndicator)
            _childrenList.Clear();

        _childrenList.Add(child);

        SetChildPropertiesFromParent(child);
    }

    protected void SetChildPropertiesFromParent(perTreeViewItemViewModelBase child)
    {
        child.Parent = this;

        // if this node is checked then all new children added are set checked
        if (IsChecked.GetValueOrDefault())
            child.SetIsCheckedIncludingChildren(true);

        ReCalculateNodeCheckState();
    }

    protected void ReCalculateNodeCheckState()
    {
        var item = this;

        while (item != null)
        {
            if (item.Children.Any() && !Equals(item.Children.FirstOrDefault(), LazyLoadingChildIndicator))
            {
                var hasIndeterminateChild = item.Children.Any(c => c.IsEnabled && !c.IsChecked.HasValue);

                if (hasIndeterminateChild)
                    item.SetIsCheckedThisItemOnly(null);
                else
                {
                    var hasSelectedChild = item.Children.Any(c => c.IsEnabled && c.IsChecked.GetValueOrDefault());
                    var hasUnselectedChild = item.Children.Any(c => c.IsEnabled && !c.IsChecked.GetValueOrDefault());

                    if (hasUnselectedChild && hasSelectedChild)
                        item.SetIsCheckedThisItemOnly(null);
                    else
                        item.SetIsCheckedThisItemOnly(hasSelectedChild);
                }
            }

            item = item.Parent;
        }
    }

    private void SetIsCheckedIncludingChildren(bool? value)
    {
        if (IsEnabled)
        {
            _isChecked = value;
            RaisePropertyChanged(nameof(IsChecked));

            foreach (var child in Children)
                if (child.IsEnabled)
                    child.SetIsCheckedIncludingChildren(value);
        }
    }

    private void SetIsCheckedThisItemOnly(bool? value)
    {
        _isChecked = value;
        RaisePropertyChanged(nameof(IsChecked));
    }

    /// <summary>
    /// Add multiple children to this TreeView item
    /// </summary>
    /// <param name="children"></param>
    public void AddChildren(IEnumerable<perTreeViewItemViewModelBase> children)
    {
        foreach (var child in children)
            AddChild(child);
    }

    /// <summary>
    /// Remove a child item from this TreeView item
    /// </summary>
    public void RemoveChild(perTreeViewItemViewModelBase child)
    {
        _childrenList.Remove(child);
        child.Parent = null;

        ReCalculateNodeCheckState();
    }

    public perTreeViewItemViewModelBase Parent { get; private set; }

    private bool? _isChecked = false;

    public bool? IsChecked
    {
        get => _isChecked;
        set
        {
            if (Set(nameof(IsChecked), ref _isChecked, value))
            {
                foreach (var child in Children)
                    if (child.IsEnabled)
                        child.SetIsCheckedIncludingChildren(value);

                Parent?.ReCalculateNodeCheckState();
            }
        }
    }

    private bool _isExpanded;

    public bool IsExpanded
    {
        get => _isExpanded;
        set
        {
            if (Set(nameof(IsExpanded), ref _isExpanded, value) && value && RequiresLazyLoad)
                TriggerLazyLoading();
        }
    }

    private bool _isEnabled = true;

    public bool IsEnabled
    {
        get => _isEnabled;
        set => Set(nameof(IsEnabled), ref _isEnabled, value);
    }

    public void TriggerLazyLoading()
    {
        var unused = DoLazyLoadAsync();
    }

    private async Task DoLazyLoadAsync()
    {
        if (LazyLoadTriggered)
            return;

        LazyLoadTriggered = true;

        var lazyChildrenResult = await LazyLoadFetchChildren()
            .EvaluateFunctionAsync()
            .ConfigureAwait(false);

        LazyLoadCompleted = true;

        if (lazyChildrenResult.IsCompletedOk)
        {
            var lazyChildren = lazyChildrenResult.Data;

            foreach (var child in lazyChildren)
                SetChildPropertiesFromParent(child);

            // If LazyLoadChildren has been overridden then just refresh the check state (using the new children)
            // and update the check state (in case any of the new children is already set as checked)
            if (LazyLoadChildrenOverridden)
                ReCalculateNodeCheckState();
            else
                AddChildren(lazyChildren); // otherwise add the new children to the base collection.
        }

        RefreshChildren();
    }

    /// <summary>
    /// Get the children for this node, in Lazy-Loading Mode
    /// </summary>
    /// <returns></returns>
    protected virtual Task<perTreeViewItemViewModelBase[]> LazyLoadFetchChildren()
    {
        return Task.FromResult(new perTreeViewItemViewModelBase[0]);
    }

    /// <summary>
    /// Update the Children property
    /// </summary>
    public void RefreshChildren()
    {
        RaisePropertyChanged(nameof(Children));
    }

    /// <summary>
    /// In LazyLoading Mode, the Children property can be set to something other than
    /// the base _childrenList collection - e.g as the union ot two internal collections
    /// </summary>
    public IEnumerable<perTreeViewItemViewModelBase> Children => LazyLoadCompleted
                                                                ? LazyLoadChildren
                                                                : _childrenList;

    /// <summary>
    /// How are the children held when in lazy loading mode.
    /// </summary>
    /// <remarks>
    /// Override this as required in descendent classes - e.g. if Children is formed from a union
    /// of multiple internal child item collections (of different types) which are populated in LazyLoadFetchChildren()
    /// </remarks>
    protected virtual IEnumerable<perTreeViewItemViewModelBase> LazyLoadChildren => _childrenList;

    private bool _isSelected;

    public bool IsSelected
    {
        get => _isSelected;
        set
        {
            // if unselecting we don't care about anything else other than simply updating the property
            if (!value)
            {
                Set(nameof(IsSelected), ref _isSelected, false);
                return;
            }

            // Build a priority queue of operations
            //
            // All operations relating to tree item expansion are added with priority = DispatcherPriority.ContextIdle, so that they are
            // sorted before any operations relating to selection (which have priority = DispatcherPriority.ApplicationIdle).
            // This ensures that the visual container for all items are created before any selection operation is carried out.
            //
            // First expand all ancestors of the selected item - those closest to the root first
            //
            // Expanding a node will scroll as many of its children as possible into view - see perTreeViewItemHelper, but these scrolling
            // operations will be added to the queue after all of the parent expansions.
            var ancestorsToExpand = new Stack<perTreeViewItemViewModelBase>();

            var parent = Parent;
            while (parent != null)
            {
                if (!parent.IsExpanded)
                    ancestorsToExpand.Push(parent);

                parent = parent.Parent;
            }

            while (ancestorsToExpand.Any())
            {
                var parentToExpand = ancestorsToExpand.Pop();
                perDispatcherHelper.AddToQueue(() => parentToExpand.IsExpanded = true, DispatcherPriority.ContextIdle);
            }

            // Set the item's selected state - use DispatcherPriority.ApplicationIdle so this operation is executed after all
            // expansion operations, no matter when they were added to the queue.
            //
            // Selecting a node will also scroll it into view - see perTreeViewItemHelper
            perDispatcherHelper.AddToQueue(() => Set(nameof(IsSelected), ref _isSelected, true), DispatcherPriority.ApplicationIdle);

            // note that by rule, a TreeView can only have one selected item, but this is handled automatically by
            // the control - we aren't required to manually unselect the previously selected item.

            // execute all of the queued operations in descending DispatcherPriority order (expansion before selection)
            var unused = perDispatcherHelper.ProcessQueueAsync();
        }
    }

    public override string ToString()
    {
        return Caption;
    }

    /// <summary>
    /// What's the total number of child nodes beneath this one
    /// </summary>
    public int ChildCount => Children.Count() + Children.Sum(c => c.ChildCount);
}

Amongst other features, it includes a Parent property, so each item in the data structure knows its immediate ancestor.

Rather than using an event to handle an item being clicked, I've created a behaviour to add a bindable selected item property to a TreeView. This allows a change of selection to be detected for means other than a direct mouse click, such as the user pressing the arrow keys.

public class perTreeViewHelper : Behavior<TreeView>
{
    public object BoundSelectedItem
    {
        get => GetValue(BoundSelectedItemProperty);
        set => SetValue(BoundSelectedItemProperty, value);
    }

    public static readonly DependencyProperty BoundSelectedItemProperty =
        DependencyProperty.Register("BoundSelectedItem",
            typeof(object),
            typeof(perTreeViewHelper),
            new FrameworkPropertyMetadata(null,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                OnBoundSelectedItemChanged));

    private static void OnBoundSelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue is perTreeViewItemViewModelBase item)
            item.IsSelected = true;
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
        base.OnDetaching();
    }

    private void OnTreeViewSelectedItemChanged(object obj, RoutedPropertyChangedEventArgs<object> args)
    {
        BoundSelectedItem = args.NewValue;
    }
}

More details on my blog post


来源: stackexchange

问:
Is there a STL algorithm that finds last but that it also works on pointers?
I have existing code where I can not switch to iterators.
Still I would like to use STL if possible to find the last item(or first if you consider we are iterating from end).
Is that possible?

std::find_end beside being worst named algorithm ever seems quite ugly to use(I would need a fake 1 element sequence and binary predicate that ignores values of 1 element in comparison).

What I have now is quite ugly(especially since reverse of reverse of bool* is not bool* so I have to do ugly stuff to get std::distance.

```<code>#include <algorithm>
#include <iostream>

int main()
{
    {
    bool arr[6] = {true,false,true,true,true,false};
    auto e = std::make_reverse_iterator(&arr[0]);
    auto b = std::make_reverse_iterator(&arr[6]);
    auto it = std::find(b,e, false);
    if (it!=e){
        std::cout << "index of last false is " << &(*it) - &arr[0] << std::endl;
    }
    }
    // repeat test to make sure result is not an accident
    {
    bool arr[6] = {true,false,true,true,false,true};
    auto e = std::make_reverse_iterator(&arr[0]);
    auto b = std::make_reverse_iterator(&arr[6]);
    auto it = std::find(b,e, false);
    if (it!=e){
        std::cout << "index of last false is " << &(*it) - &arr[0] << std::endl;
    }
    }
}
</code>```

答:
The correct way to find the index of the last element in a container (including c arrays) is using std::find with reverse_iterators (For bidirectional containers) just like you have tried but with less UB (&arr[6] is UB).

```<code>using std::begin;
using std::rbegin;
using std::rend;

bool arr[6] = {...};
auto it = std::find(rbegin(arr), rend(arr), false);
if (it != rend(arr)) {
    auto idx = std::distance(begin(arr), it.base()) - 1;
    std::cout << "idx is " << idx << std::endl;
}
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I have existing code where I can not switch to iterators.
Still I would like to use STL if possible to find the last item(or first if you consider we are iterating from end).
Is that possible?

std::find_end beside being worst named algorithm ever seems quite ugly to use(I would need a fake 1 element sequence and binary predicate that ignores values of 1 element in comparison).

What I have now is quite ugly(especially since reverse of reverse of bool* is not bool* so I have to do ugly stuff to get std::distance.

#include <algorithm>
#include <iostream>

int main()
{
    {
    bool arr[6] = {true,false,true,true,true,false};
    auto e = std::make_reverse_iterator(&arr[0]);
    auto b = std::make_reverse_iterator(&arr[6]);
    auto it = std::find(b,e, false);
    if (it!=e){
        std::cout << "index of last false is " << &(*it) - &arr[0] << std::endl;
    }
    }
    // repeat test to make sure result is not an accident
    {
    bool arr[6] = {true,false,true,true,false,true};
    auto e = std::make_reverse_iterator(&arr[0]);
    auto b = std::make_reverse_iterator(&arr[6]);
    auto it = std::find(b,e, false);
    if (it!=e){
        std::cout << "index of last false is " << &(*it) - &arr[0] << std::endl;
    }
    }
}

Body:
The correct way to find the index of the last element in a container (including c arrays) is using std::find with reverse_iterators (For bidirectional containers) just like you have tried but with less UB (&arr[6] is UB).

using std::begin;
using std::rbegin;
using std::rend;

bool arr[6] = {...};
auto it = std::find(rbegin(arr), rend(arr), false);
if (it != rend(arr)) {
    auto idx = std::distance(begin(arr), it.base()) - 1;
    std::cout << "idx is " << idx << std::endl;
}


问:
Django command python manage.py runserver is not working
The command python manage.py runserver is not giving any response. When i press enter after typing command  then the only thing which i get is:

```<code>HP@LAPTOP-3446CCM0 MINGW64 ~/downloads/src7/src7/mysite
$ python manage.py runserver
Watching for file changes with StatReloader
</code>```

Nothing after this appears on the screen. But when i press CTRL+C then something like this appears on the screen:

```<code>$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
May 29, 2020 - 15:38:05
Django version 3.0.6, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
</code>```

How to overcome through this

答:
The server is working correctly, visit http://127.0.0.1:8000/ in your browser to see.

The message is telling you that you need to run migrations on your database. run python manage.py migrate and it will set up your database and remove that console output

Edit: To remove the stat reloader, you need to run the server with: python manage.py runserver --noreload

Body:
The command python manage.py runserver is not giving any response. When i press enter after typing command  then the only thing which i get is:

HP@LAPTOP-3446CCM0 MINGW64 ~/downloads/src7/src7/mysite
$ python manage.py runserver
Watching for file changes with StatReloader

Nothing after this appears on the screen. But when i press CTRL+C then something like this appears on the screen:

$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
May 29, 2020 - 15:38:05
Django version 3.0.6, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

How to overcome through this


问:
Discord SDK Terminates Unity Editor when Discord is not running
This question doesn't really contain any code...

I Added the Discord SDK to my project and every time I run the game, it Closes the Unity Editor.
Is there a way to stop the Discord SDK from terminating the Editor?

答:
@EliasV you need Discord app running when trying to launch the game in Editor.

```<code>/*
    Grab that Client ID from earlier
    Discord.CreateFlags.Default will require Discord to be running for the game to work
    If Discord is not running, it will:
    1. Close your game
    2. Open Discord
    3. Attempt to re-open your game
    Step 3 will fail when running directly from the Unity editor
    Therefore, always keep Discord running during tests, or use Discord.CreateFlags.NoRequireDiscord
*/
</code>```

https://discord.com/developers/docs/game-sdk/sdk-starter-guide

Body:
@EliasV you need Discord app running when trying to launch the game in Editor.

/*
    Grab that Client ID from earlier
    Discord.CreateFlags.Default will require Discord to be running for the game to work
    If Discord is not running, it will:
    1. Close your game
    2. Open Discord
    3. Attempt to re-open your game
    Step 3 will fail when running directly from the Unity editor
    Therefore, always keep Discord running during tests, or use Discord.CreateFlags.NoRequireDiscord
*/

https://discord.com/developers/docs/game-sdk/sdk-starter-guide


问:
what is the use of ! sign in some ruby methods

Possible Duplicate:

  Why are exclamation marks used in Ruby methods?

Hi All,

In ruby/rails I have seen some methods ended up with ! sign like

```<code>before_filter :authenticated!
</code>```

just wonder what does mean by authenticated!, '!' sign

thanks in advance

cheers

sameera

答:
Methods ending in ! usually transforms the object it is called upon as opposed to the methods without ! which performs an action and returns a new object.They are termed as "dangerous methods" in Ruby as they may change state that someone else might have a reference to.

Examples of such pairs of methods include sort/sort! for arrays, upcase/upcase! for strings, chomp/chomp! for strings, and reverse/reverse! for strings and arrays. In each case, if you call the non-bang version of the method on the object, you get a new object. If you call the bang version, you operate in-place on the same object to which you sent the message.

ContentLicense: CC BY-SA 3.0

Body:
Possible Duplicate:

  Why are exclamation marks used in Ruby methods?

Hi All,

In ruby/rails I have seen some methods ended up with ! sign like

before_filter :authenticated!

just wonder what does mean by authenticated!, '!' sign

thanks in advance

cheers

sameera


问:
Can you use Package.swift in an iOS app instead of using .xcodeproj?
I had been adding Swift package dependencies to my iOS app project using File -> Swift Packages -> Add Package Dependency.  But is it possible to use a Package.swift instead?  I thought I would just be able to drop in a Package.swift and it would start using that to resolved my packages. I'm using Cocoapods too, so I can't generate a new xcodeproj file.</p>

答:
To manage your project's swift packages dependencies with Package.swift file you should make next steps:

Create a workspace that has your project (if you don't have)

Create empty swift package e.g. "Dependencies" inside your project's folder

Add the package to your workspace (just drag and drop the folder with swift package)

Link your project's target with "Dependencies": "Build Phases -> Link Binary With Libraries"

Add your dependencies to Package.swift:

let package = Package(
    name: "Dependencies",
    ...
    dependencies: [
        .package(url: "https://github.com/username/SwiftPackage.git", .exact("1.1.0")),
    ],
    targets: [
        .target(
            name: "Dependencies",
            dependencies: ["SwiftPackage"]),
        ...
    ]
)
```

Now all swift package dependencies are available in your project automatically after editing Package.swift file.

UPDATE

There is the second much stable option to add Dependencies swift package to your project:

Create an empty swift package e.g. "Dependencies" inside your project's folder.

Add your dependencies to Package.swift (see above).

Create a local git repository in "Dependencies" folder and commit all files to master.

Add "Dependencies" swift package in "Swift Packages" tab of your project's settings by providing a full path file:///Users/.../Dependencies (Xcode allows adding by a full path only) and point it to master branch.

If you need to use a relative path instead just do next trick: change XCRemoteSwiftPackageReference > repositoryURL value manually to file://Dependencies in your project.pbxproj file and then you can see:

NOTE: you need to push all changes to master each time after changing your dependencies in Package.swift file to allow your project to see them.

Body:
To manage your project's swift packages dependencies with Package.swift file you should make next steps:

Create a workspace that has your project (if you don't have)

Create empty swift package e.g. "Dependencies" inside your project's folder

Add the package to your workspace (just drag and drop the folder with swift package)

Link your project's target with "Dependencies": "Build Phases -> Link Binary With Libraries"

Add your dependencies to Package.swift:

let package = Package(
    name: "Dependencies",
    ...
    dependencies: [
        .package(url: "https://github.com/username/SwiftPackage.git", .exact("1.1.0")),
    ],
    targets: [
        .target(
            name: "Dependencies",
            dependencies: ["SwiftPackage"]),
        ...
    ]
)

Now all swift package dependencies are available in your project automatically after editing Package.swift file.

UPDATE

There is the second much stable option to add Dependencies swift package to your project:

Create an empty swift package e.g. "Dependencies" inside your project's folder.

Add your dependencies to Package.swift (see above).

Create a local git repository in "Dependencies" folder and commit all files to master.

Add "Dependencies" swift package in "Swift Packages" tab of your project's settings by providing a full path file:///Users/.../Dependencies (Xcode allows adding by a full path only) and point it to master branch.

If you need to use a relative path instead just do next trick: change XCRemoteSwiftPackageReference > repositoryURL value manually to file://Dependencies in your project.pbxproj file and then you can see:

NOTE: you need to push all changes to master each time after changing your dependencies in Package.swift file to allow your project to see them.


问:
Web scraping for sites that need login
First of all I'm not a python expert. I'm learning python to scrape data from this specific game website.
I'm trying to scrape data from a website that need login.
You won't see data unless you login to this website.(I have attached a screenshot of page you will see for above website once you login)
I tried to run the following code:

import requests
from bs4 import BeautifulSoup

page = requests.get('<website url>')
soup = BeautifulSoup(page.content, 'html.parser')
print(soup)```

Here, I'm getting same result as if i'm not logged in to this website.
Can someone guide me what I need to do?

enter image description here

答:
You can use requests.session() to login and then make next requests.

For example:

```<code>import requests
from bs4 import BeautifulSoup

data = {'lEmail': '<YOUR EMAIL HERE>',
        'lPass': '<YOUR PASSWORD HERE>',
        'fbSig': 'web'}

url = 'https://www.airline4.net/research_main.php?mode=search&rwy=1000&dist=25000&depId=3982&arr=0&arrId=0&fbSig=false'
login_url = 'https://www.airline4.net/weblogin/login.php'

with requests.session() as s:
    s.post(login_url, data=data).text

    # now you are logged in, just print some information:
    soup = BeautifulSoup(s.get(url).content, 'html.parser')
    print(soup.get_text(strip=True, separator='\n'))
</code>```

Prints:

```<code>Distance
Y class
J class
F class
Rwy
OPIS
-
SCIP
Pakistan, Islamabad
-
Chile, Isla De Pascua
19,273 km
10,827ft rwy
Market:
55%
Y class
473
J class
221
F class
129
OPIS
-
NTGJ
Pakistan, Islamabad
-
French Polynesia, Totegegie
17,075 km
6,562ft rwy
Market:
67%
Y class
286
J class
161
F class
21
OPIS
-

... and so on.
</code>```

Title: Web scraping for sites that need login

Body:
First of all I'm not a python expert. I'm learning python to scrape data from this specific game website.
I'm trying to scrape data from a website that need login.
You won't see data unless you login to this website.(I have attached a screenshot of page you will see for above website once you login)
I tried to run the following code:

import requests
from bs4 import BeautifulSoup

page = requests.get('<website url>')
soup = BeautifulSoup(page.content, 'html.parser')
print(soup)

Here, I'm getting same result as if i'm not logged in to this website.
Can someone guide me what I need to do?

enter image description here

Body:
You can use requests.session() to login and then make next requests.

For example:

import requests
from bs4 import BeautifulSoup

data = {'lEmail': '<YOUR EMAIL HERE>',
        'lPass': '<YOUR PASSWORD HERE>',
        'fbSig': 'web'}

url = 'https://www.airline4.net/research_main.php?mode=search&rwy=1000&dist=25000&depId=3982&arr=0&arrId=0&fbSig=false'
login_url = 'https://www.airline4.net/weblogin/login.php'

with requests.session() as s:
    s.post(login_url, data=data).text

    # now you are logged in, just print some information:
    soup = BeautifulSoup(s.get(url).content, 'html.parser')
    print(soup.get_text(strip=True, separator='\n'))

Prints:

Distance
Y class
J class
F class
Rwy
OPIS
-
SCIP
Pakistan, Islamabad
-
Chile, Isla De Pascua
19,273 km
10,827ft rwy
Market:
55%
Y class
473
J class
221
F class
129
OPIS
-
NTGJ
Pakistan, Islamabad
-
French Polynesia, Totegegie
17,075 km
6,562ft rwy
Market:
67%
Y class
286
J class
161
F class
21
OPIS
-

... and so on.


问:
Correct way to add cache-control and expires headers to all S3 files but prevent them from becoming inaccessible?
In how to add cache control in AWS S3? someone said that

```<code>./s3cmd
--recursive modify
--add-header="Cache-Control:max-age=86400"
s3://yourbucket/
</code>```

as the correct command to add cache-control (and also expires) headers, but many people then said that it removed accessibility to the files (access denied).

Apparently it works if you run it folder by folder but that's not easy when you have thousands of folders.

What is the correct command to avoid this?

UPDATE 1: Could using --add-header='Cache-Control:max-age=86400, public' be a solution?

答:
Here is a solution, you can modify the files by adding the expiry headers recursively.

The code

```<code>s3cmd --recursive modify --add-header="Cache-Control:public ,max-age=31536000" s3://your_bucket_name/
</code>```

Your files won't get inaccessible while doing this.

Body:
In how to add cache control in AWS S3? someone said that

./s3cmd
--recursive modify
--add-header="Cache-Control:max-age=86400"
s3://yourbucket/

as the correct command to add cache-control (and also expires) headers, but many people then said that it removed accessibility to the files (access denied).

Apparently it works if you run it folder by folder but that's not easy when you have thousands of folders.

What is the correct command to avoid this?

UPDATE 1: Could using --add-header='Cache-Control:max-age=86400, public' be a solution?

Body:
Here is a solution, you can modify the files by adding the expiry headers recursively.

The code

s3cmd --recursive modify --add-header="Cache-Control:public ,max-age=31536000" s3://your_bucket_name/

Your files won't get inaccessible while doing this.


问:
How to resize image with ImageTk/Image from PIL
Here is the full code

```<code>import tkinter as tk
from PIL import ImageTk, Image

def hide_screen():
    window.overrideredirect(0)
    window.iconify()

def screen_appear(event):
    window.overrideredirect(1)

def callback(event):
    window.geometry("+{0}+{1}".format(event.x_root,event.y_root))

window = tk.Tk()
window.geometry("400x200")
window.overrideredirect(True)

title_bar = tk.Frame(window, bg="#2c2c2c", bd=0)

title_bar_logo = ImageTk.PhotoImage(Image.open("title_bar_logo.png"))
title_bar_logo = ImageTk.resize((250, 250), Image.ANTIALIAS)
panel = tk.Label(title_bar, image=title_bar_logo)
label1 = tk.Label(title_bar, text="Title Bar", fg="gold2", bg="#2c2c2c", font="Times")
close_button = tk.Button(title_bar, text="X", bg="red", command=window.destroy, bd=0)
minimise_button = tk.Button(title_bar, text="-", bg="red", command=hide_screen, bd=0)

window2 = tk.Canvas(window, bg="#1b1b1b", highlightthickness=0)

title_bar.pack(fill="x")
panel.pack(side=tk.LEFT)
close_button.pack(side=tk.RIGHT)
minimise_button.pack(side=tk.RIGHT)
window2.pack(expand=1, fill="x")
label1.pack(anchor=tk.CENTER)

title_bar.bind("<Map>", screen_appear)
title_bar.bind("<B1-Motion>", callback)
window.mainloop()
</code>```

And here are the image lines

```<code>title_bar_logo = ImageTk.PhotoImage(Image.open("title_bar_logo.png"))
title_bar_logo = ImageTk.resize((250, 250), Image.ANTIALIAS)
panel = tk.Label(title_bar, image=title_bar_logo)
panel.pack(side=tk.LEFT)
</code>```

i have tried soo many things but i can't get it to work
and i really hope you can find an answer for me

thank you in advance

答:
I use it as example it working well:

```<code>logo = Image.open("title_bar_logo.png")
logo = logo.resize((20,15), Image.ANTIALIAS)
title_bar_logo=ImageTk.PhotoImage(logo)
</code>```

use :

```<code>title_bar_logo
</code>```

in your code

Body:
Here is the full code

import tkinter as tk
from PIL import ImageTk, Image

def hide_screen():
    window.overrideredirect(0)
    window.iconify()

def screen_appear(event):
    window.overrideredirect(1)

def callback(event):
    window.geometry("+{0}+{1}".format(event.x_root,event.y_root))

window = tk.Tk()
window.geometry("400x200")
window.overrideredirect(True)

title_bar = tk.Frame(window, bg="#2c2c2c", bd=0)

title_bar_logo = ImageTk.PhotoImage(Image.open("title_bar_logo.png"))
title_bar_logo = ImageTk.resize((250, 250), Image.ANTIALIAS)
panel = tk.Label(title_bar, image=title_bar_logo)
label1 = tk.Label(title_bar, text="Title Bar", fg="gold2", bg="#2c2c2c", font="Times")
close_button = tk.Button(title_bar, text="X", bg="red", command=window.destroy, bd=0)
minimise_button = tk.Button(title_bar, text="-", bg="red", command=hide_screen, bd=0)

window2 = tk.Canvas(window, bg="#1b1b1b", highlightthickness=0)

title_bar.pack(fill="x")
panel.pack(side=tk.LEFT)
close_button.pack(side=tk.RIGHT)
minimise_button.pack(side=tk.RIGHT)
window2.pack(expand=1, fill="x")
label1.pack(anchor=tk.CENTER)

title_bar.bind("<Map>", screen_appear)
title_bar.bind("<B1-Motion>", callback)
window.mainloop()

And here are the image lines

title_bar_logo = ImageTk.PhotoImage(Image.open("title_bar_logo.png"))
title_bar_logo = ImageTk.resize((250, 250), Image.ANTIALIAS)
panel = tk.Label(title_bar, image=title_bar_logo)
panel.pack(side=tk.LEFT)

i have tried soo many things but i can't get it to work
and i really hope you can find an answer for me

thank you in advance

Body:
I use it as example it working well:

logo = Image.open("title_bar_logo.png")
logo = logo.resize((20,15), Image.ANTIALIAS)
title_bar_logo=ImageTk.PhotoImage(logo)

use :

title_bar_logo

in your code


问:
Change the header cell background color
I want to set the background color of table header cell on the click of cell .

Below is the css by which I am setting the background of table header cell .

#tblid > thead > tr > th {
    color: #515151;
    background: #b6e9fc;
}```

Now, on click of header cell when I am setting different color then  new color is not appearing on UI instead original background hides the new background color .I can see the new color in developer tool if we remove the original background color from the above css.

Could you please suggest some solution for this problem .I don't  want to remove the background color first and then set the new because If I remove the original background then complete header row will lost the background.Please suggest some better way to achieve this .

Thanks .

答:
I achieved this through css only by applying the active selector. I am able to set the background color of th cell after clicking on header cell.

#tblid > thead > tr > th:active {
        color: #515151;
        background: #86dafa;
 }```
<pre class="snippet-code-html lang-html prettyprint-override"><code><table id="tblid">
  <thead>
    <tr>
      <th>Header</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Cell</th>
    </tr>
  </tbody>
</table></code>```

Title: Change the header cell background color

Body:
I want to set the background color of table header cell on the click of cell .

Below is the css by which I am setting the background of table header cell .

#tblid > thead > tr > th {
    color: #515151;
    background: #b6e9fc;
}

Now, on click of header cell when I am setting different color then  new color is not appearing on UI instead original background hides the new background color .I can see the new color in developer tool if we remove the original background color from the above css.

Could you please suggest some solution for this problem .I don't  want to remove the background color first and then set the new because If I remove the original background then complete header row will lost the background.Please suggest some better way to achieve this .

Thanks .

Body:
I achieved this through css only by applying the active selector. I am able to set the background color of th cell after clicking on header cell.

#tblid > thead > tr > th:active {
        color: #515151;
        background: #86dafa;
 }

<table id="tblid">
  <thead>
    <tr>
      <th>Header</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Cell</th>
    </tr>
  </tbody>
</table>


问:
generating and mapping two sets of numbers
I have 2 numbers 25798709 and 25716544 representing the minimum and maximum values of some consecutive numbers with each number differing from the preceeding number by one eg. 25798709,25798710, 25798711................25716544  I want a python code that will convert these figures to 1,2,3,4,5,.............. and map the 1,2,3,4,5 to the original figures in two columns:
Like: </p>

```<code>  1     25798709
  2     25798710
  3     25798711
</code>```

答:
Here you are:

```<code>mapping = dict(enumerate(range(25716544, 25798709)))
for i in iter(mapping):
    print i, '->', mapping[i]
</code>```

I should warn you that this is zero-based. So 0 -> 25716544, 1 -> 25716545, etc.

Body:
I have 2 numbers 25798709 and 25716544 representing the minimum and maximum values of some consecutive numbers with each number differing from the preceeding number by one eg. 25798709,25798710, 25798711................25716544  I want a python code that will convert these figures to 1,2,3,4,5,.............. and map the 1,2,3,4,5 to the original figures in two columns:
Like:

  1     25798709
  2     25798710
  3     25798711

Body:
Here you are:

mapping = dict(enumerate(range(25716544, 25798709)))
for i in iter(mapping):
    print i, '->', mapping[i]

I should warn you that this is zero-based. So 0 -> 25716544, 1 -> 25716545, etc.


问:
How do I identify which DAG / task is causing Node memory issues?
Tasks are regularly failing in our DAGs, and after following Google's troubleshooting steps I've identified the underlying cause to be memory evictions due to insufficient memory.

This matches what I'm seeing in the Memory utilization per node graph in the Composer Monitoring tab. Our machine supports 8 GB nodes and the largest spikes are 16 GB.

Screen shot of memory utilization per node graph, which shows memory spikes

Where I'm stuck is identifying which DAGs are causing the memory spikes. (My assumption is that "DAG A" may be causing the memory spike which led to "DAG B" being evicted). I'd like to revisit the code to see if it can be optimized before increasing the machine size.

How do I connect the dots to understand which tasks were being handled by a given Kubernetes Node at a given time?

答:
If you need to know which DAG is running in which instance in a given time, one approach is using Airflow Metadata Database.
For that, follow the steps below:

Go to GKE page and click on your cluster.

In your cluster's page, click on the Connect button on the top of the page (between Deploy and Duplicate)

A pop-up window will open  with two options. Click on Run in Cloud Shell. After that, a Cloud Shell instance will be opened with a command like below. Just press enter to submit this command.

```<code>gcloud container clusters get-credentials <cluter_id> --zone <cluster_zone> --project <project_id>`
</code>```

Then run the command below to deploy a temporary MySQL image

```<code>kubectl run mysql-cli-tmp-deployment \
--generator=run-pod/v1 \
--rm --stdin --tty \
--image mysql:latest \
-- \
  bash
</code>```

Run the command below to connect to your MySQL instance

```<code>mysql \
--user root \
--host airflow-sqlproxy-service.default
</code>```

Now you can use SHOW DATABASES; to determine what database we need. If you're using new versions of Composer, the database name will be something like composer-< some_version >-airflow-< some_version >-< some_hash >. For old versions, the name will be airflow-db. After determining your database, just enter the command use <your_database>;

Now if you run SHOW TABLES: you will find a lot of different information. For your purpose, I suggest that you run  select * from job limit 10;
By running this query you will see that this table has many information about the tasks: DAG id, start date, end date ,hostname(there is one hostname for each node in your cluster) [...]

Finally, as a last step I would like to explain how can you determine which is hostname is associated with which node.

Go to GKE page and click on Workloads

Click on airflow-worker

Scroll down to the Managed pods section and you will find the hostnames. If you click on any of them, you will be able to see its node in the next page.

With these information you will be able to run queries to determine which DAG is running in which instance in a given time.

Body:
If you need to know which DAG is running in which instance in a given time, one approach is using Airflow Metadata Database.
For that, follow the steps below:

Go to GKE page and click on your cluster.

In your cluster's page, click on the Connect button on the top of the page (between Deploy and Duplicate)

A pop-up window will open  with two options. Click on Run in Cloud Shell. After that, a Cloud Shell instance will be opened with a command like below. Just press enter to submit this command.

gcloud container clusters get-credentials <cluter_id> --zone <cluster_zone> --project <project_id>`

Then run the command below to deploy a temporary MySQL image

kubectl run mysql-cli-tmp-deployment \
--generator=run-pod/v1 \
--rm --stdin --tty \
--image mysql:latest \
-- \
  bash

Run the command below to connect to your MySQL instance

mysql \
--user root \
--host airflow-sqlproxy-service.default

Now you can use SHOW DATABASES; to determine what database we need. If you're using new versions of Composer, the database name will be something like composer-< some_version >-airflow-< some_version >-< some_hash >. For old versions, the name will be airflow-db. After determining your database, just enter the command use <your_database>;

Now if you run SHOW TABLES: you will find a lot of different information. For your purpose, I suggest that you run  select * from job limit 10;
By running this query you will see that this table has many information about the tasks: DAG id, start date, end date ,hostname(there is one hostname for each node in your cluster) [...]

Finally, as a last step I would like to explain how can you determine which is hostname is associated with which node.

Go to GKE page and click on Workloads

Click on airflow-worker

Scroll down to the Managed pods section and you will find the hostnames. If you click on any of them, you will be able to see its node in the next page.

With these information you will be able to run queries to determine which DAG is running in which instance in a given time.


问:
How do we call this type of navigation tab menu
How do we call this tab menu with the next and preview option and also is there any material-ui component of it

答:
This type of UI elements is called "chips".

https://material-ui.com/components/chips/

Note, that usually it is not used for navigation, but rather for displaying tags, categories, etc.


问:
Process.Start(url) in a loop not launching every instance
I have a need to launch multiple browser instances / tabs in succession but using Process.Start(url) I am finding that not every URL is launched.

```<code>    for (int i = 0; i < n; i++)
    {
        var p = Process.Start("http://localhost/#" + i.ToString());
    }
</code>```

For any value n > 1 I find that only the last URL is opened in the browser (I'm testing with IE as the default browser). If I add a Thread.Sleep(1000) after Process.Start then I see a variety of behavior: sometimes all n are created; sometimes a subset.

The following does work as expected, but assumes IE (would rather use the default browser) and launches n browser instances rather than n tabs:

```<code>    for (int i = 0; i < n; i++)
    {
        var p = Process.Start("iexplore.exe", "http://localhost/#" + i.ToString());
    }
</code>```

I would prefer to get it working with the default browser behavior, but need it to be deterministic.

答:
Also see Open multiple-tabs in IE9 using Process (possible duplicate)

We are working on exactly this issue for IE9.  This seems to work.

```<code>bool isLaunched = false;
foreach (string url in urls)
{
    try
    {
        if (!isLaunched)
        {
            Process p = new Process();
            p.StartInfo.FileName = browser;
            p.StartInfo.Arguments = url;
            p.Start();
            Thread.Sleep(1000);
            isLaunched = true;
        }
        else
        {
            Process.Start(url);
        }
    }
    catch (Exception ex)
    {
// something

    }
}
</code>```

In my experience p.WaitForIdle does not work.  Also, there are differences in behavior if a browser instance is already open on the machine.  Calling iexplore actually passes the url to the open instance and exits your called process.

Body:
I have a need to launch multiple browser instances / tabs in succession but using Process.Start(url) I am finding that not every URL is launched.

    for (int i = 0; i < n; i++)
    {
        var p = Process.Start("http://localhost/#" + i.ToString());
    }

For any value n > 1 I find that only the last URL is opened in the browser (I'm testing with IE as the default browser). If I add a Thread.Sleep(1000) after Process.Start then I see a variety of behavior: sometimes all n are created; sometimes a subset.

The following does work as expected, but assumes IE (would rather use the default browser) and launches n browser instances rather than n tabs:

    for (int i = 0; i < n; i++)
    {
        var p = Process.Start("iexplore.exe", "http://localhost/#" + i.ToString());
    }

I would prefer to get it working with the default browser behavior, but need it to be deterministic.

Body:
Also see Open multiple-tabs in IE9 using Process (possible duplicate)

We are working on exactly this issue for IE9.  This seems to work.

bool isLaunched = false;
foreach (string url in urls)
{
    try
    {
        if (!isLaunched)
        {
            Process p = new Process();
            p.StartInfo.FileName = browser;
            p.StartInfo.Arguments = url;
            p.Start();
            Thread.Sleep(1000);
            isLaunched = true;
        }
        else
        {
            Process.Start(url);
        }
    }
    catch (Exception ex)
    {
// something

    }
}

In my experience p.WaitForIdle does not work.  Also, there are differences in behavior if a browser instance is already open on the machine.  Calling iexplore actually passes the url to the open instance and exits your called process.


问:
ERROR: The instance or operation is not in an appropriate state to handle the request
Using Google Cloud SQL I was attempting to restore my main instance to a prior backup, but first I wanted to clone the instance for the tables and databases that I didn't want reverted.
After waiting over an hour for the clone, I canceled out of the clone and attempted to delete the cloned instance. However, the clone is now stuck in Maintenance status and attempting to delete I get the following error.

```<code>mycomputer:~ myuser$ gcloud sql instances delete cloned
All of the instance data will be lost when the instance is deleted.

Do you want to continue (Y/n)?  y

ERROR: (gcloud.sql.instances.delete) The instance or operation is not in an appropriate state to handle the request.
</code>```

The instance was created with the following command and then just exited out with CTRL+C after waiting too long.

```<code>mycomputer:~ myuser$ gcloud sql instances clone main cloned
Cloning Cloud SQL instance.../ERROR: Caught socket error, retrying:[Errno 54] Connection reset by peer
ERROR: Caught socket error, retrying: [Errno 54] Connection reset by peer
Cloning Cloud SQL instance...|
Cloning Cloud SQL instance...\^C

Command killed by keyboard interrupt
</code>```

答:
I was getting this error while creating SQL instance in GCP with terraform

Error: Error, failed to create instance <name>: googleapi: Error 409: The instance or operation is not in an appropriate state to handle the request., invalidState

I was able to solve it by changing the SQL instance name in the conf and it worked like perfectly

Body:
Using Google Cloud SQL I was attempting to restore my main instance to a prior backup, but first I wanted to clone the instance for the tables and databases that I didn't want reverted.
After waiting over an hour for the clone, I canceled out of the clone and attempted to delete the cloned instance. However, the clone is now stuck in Maintenance status and attempting to delete I get the following error.

mycomputer:~ myuser$ gcloud sql instances delete cloned
All of the instance data will be lost when the instance is deleted.

Do you want to continue (Y/n)?  y

ERROR: (gcloud.sql.instances.delete) The instance or operation is not in an appropriate state to handle the request.

The instance was created with the following command and then just exited out with CTRL+C after waiting too long.

mycomputer:~ myuser$ gcloud sql instances clone main cloned
Cloning Cloud SQL instance.../ERROR: Caught socket error, retrying:[Errno 54] Connection reset by peer
ERROR: Caught socket error, retrying: [Errno 54] Connection reset by peer
Cloning Cloud SQL instance...|
Cloning Cloud SQL instance...\^C

Command killed by keyboard interrupt


问:
Github - Is it posible to have private code in a public directory?
For my project, I need to send push notifications, but the private VapID key should not be visible for anyone on my public directory. Is it possible to have one file or one line not visible public, although it is a pubic GitHub directory? </p>

答:
Short answer, No.

You might want to consider having that injected in for your release in your release/build pipeline via file or ENV variable.
You could also use a mechanism like Rails secrets where there is an ecrypted file in your repo to which only you hold the key and inject the key for deployment.


问:
R data table, how to create a new column, where the answer is dependent to Another column within the DT
Hi I want to create a new column, whose answer are based on another column in my Existing DT.
I would like to use functions within the data table parameter to maximise efficiency.

```<code>smoked <- matrix(c("A","A","A","B","B","B","A","B","A"),ncol=3,byrow=TRUE)
colnames(smoked) <- c("Type","Name","cusip")
rownames(smoked) <- c("A","B","C")
smoked <- as.table(smoked)
smoked
</code>```

How would i create a another column that that responds "B" every occasion the condition is met within the "name" column.. and then "not B" for every occasion it does not.

答:
Suppose you have a data.table

library(data.table)

smoked <- data.table(Type=c("A", "B", "A"), Name=c("A", "B", "B"), cusip=c("A", "B", "A"))

# > smoked
#    Type Name cusip
# 1:    A    A     A
# 2:    B    B     B
# 3:    A    B     A
```

<p>and you want to create a new column based on <code>Type</code> and <code>Name</code>, then</p>

<pre class="lang-r prettyprint-override"><code>smoked$NewLine <- fifelse(smoked$Type == "A" & smoked$Name == "A", "B", "not B")
</code>```

gives you

> smoked
   Type Name cusip NewLine
1:    A    A     A       B
2:    B    B     B   not B
3:    A    B     A   not B
```

Body:
Hi I want to create a new column, whose answer are based on another column in my Existing DT.
I would like to use functions within the data table parameter to maximise efficiency.

smoked <- matrix(c("A","A","A","B","B","B","A","B","A"),ncol=3,byrow=TRUE)
colnames(smoked) <- c("Type","Name","cusip")
rownames(smoked) <- c("A","B","C")
smoked <- as.table(smoked)
smoked

How would i create a another column that that responds "B" every occasion the condition is met within the "name" column.. and then "not B" for every occasion it does not.

Body:
Suppose you have a data.table

library(data.table)

smoked <- data.table(Type=c("A", "B", "A"), Name=c("A", "B", "B"), cusip=c("A", "B", "A"))

# > smoked
#    Type Name cusip
# 1:    A    A     A
# 2:    B    B     B
# 3:    A    B     A

and you want to create a new column based on Type and Name, then

smoked$NewLine <- fifelse(smoked$Type == "A" & smoked$Name == "A", "B", "not B")

gives you

> smoked
   Type Name cusip NewLine
1:    A    A     A       B
2:    B    B     B   not B
3:    A    B     A   not B


问:
Mirror Relational Databases to RethinkDB?
I found this article Sync Relational Databases to NoSQL like MongoDB and was sad to see only MongoDB on the dropdown list:

Is it possible to sync a relational database to RethinkDB with SymmetricDS or any other similar tool?

答: It should be, but you’d need to add yourself support for it. The process is quite straightforward once you understood how it works for other database managers (mostly copy/paste with some modifications and lots of tryouts)</p>


问:
UIView needs to push a UIViewController (delegation)
I'm having a hard time getting my head around custom delegation - I would be most grateful if someone could help me:

I have a UIViewController with a tab bar controller, and each of these contains a subclassed UIView. In one of the views, I have a UIButton in which I want to load a UIDocumentInteractionController. I already have the code to do this second part, as the document controller needs access to a UIViewController in order to get pushed to the stack.

But how can my UIView get access to the UIViewController?

I've read a plethora of things on SO tonight, such as:

It can't be done

Set the UIViewController as a property of the UIView so it knows which it belongs to

Calling nextResponder on the UIViewController

Delegation

I can happily hit my -(void)buttonPressed: (id)sender method, but where should it go from here to implement delegation? Should it just fire something like [delegate documentRequested: sender] assuming this method exists in my view controller?

Thanks in advance for any assistance.

答:
I recently posted a detailed answer on how to use custom delegation. You can check it out here: dismissModalViewController AND pass data back

What you want to do here is implement the protocol in your UIView and set the UIViewController to be it's delegate.

To help you understand the linked answer better, in the answer, secondviewcontroller is equivalent to your UIView and firstviewcontroller is equivalent to your UIViewController.