Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当我更改选项卡并返回时,所选项目的附加属性将停止工作_C#_Wpf_Xaml_Mvvm_Tabcontrol - Fatal编程技术网

C# 当我更改选项卡并返回时,所选项目的附加属性将停止工作

C# 当我更改选项卡并返回时,所选项目的附加属性将停止工作,c#,wpf,xaml,mvvm,tabcontrol,C#,Wpf,Xaml,Mvvm,Tabcontrol,我有一个视图和一个视图模型。我有一个数据网格,当我选择一行时,一个文本框显示该行的值。这只是为了显示SelectedItems是否被触发 它工作正常,但如果我切换到另一个选项卡并返回,它就会停止工作 我的看法是: <Window x:Class="TabControlError.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

我有一个视图和一个视图模型。我有一个
数据网格
,当我选择一行时,一个
文本框
显示该行的值。这只是为了显示
SelectedItems
是否被触发

它工作正常,但如果我切换到另一个选项卡并返回,它就会停止工作

我的看法是:

<Window x:Class="TabControlError.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TabControlError"
        xmlns:vm="clr-namespace:TabControlError.ViewModels"
        xmlns:dp="clr-namespace:TabControlError.DependencyProperties"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
    
    
    
    <Grid>
        <TabControl>
            <TabItem Header="Tab1">
                <Grid>
                    <TextBox Text="{Binding Text}" Width="100" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top"/>

                    <DataGrid Margin="0,40,0,0"
                              ItemsSource="{Binding Numbers}"
                              SelectedItem="{Binding NumbersSelectedItem}"
                              dp:DataGridSelectedItemsDependencyProperty.SelectedItems="{Binding NumbersSelectedItems}">

                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Number" Binding="{Binding Path=.}" Width="150"/>
                        </DataGrid.Columns>
                    </DataGrid>
                </Grid>
            </TabItem>

            <TabItem Header="Tab2"/>
        </TabControl>
    </Grid>
</Window>

为什么在我更改选项卡控件中的选项卡时它会停止工作?

WPF选项卡控件只有一个内容演示器。切换选项卡时,将卸载数据网格,并调用
unload
事件处理程序,从而删除
SelectionChanged
处理程序。当您切换回时,会再次加载数据网格,但不会更改
SelectedItems
值,因此您不会添加
SelectionChanged
处理程序,这就是为什么不会再次调用该处理程序并且不会同步项的原因

您可以将处理程序添加到数据网格的
Loaded
事件中,以重新附加同步所选项目的
SelectionChanged
处理程序。例如,类似这样的方法应该有效:

public class DataGridSelectedItemsDependencyProperty
{
   // ...your other code.

   private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
      DataGrid miDataGrid = (DataGrid)d;

      if (e.OldValue != null)
      {
         miDataGrid.SelectionChanged -= DataGrid_SelectionChanged;
         miDataGrid.Loaded -= dataGrid_Loaded;
         miDataGrid.Unloaded -= dataGrid_Unloaded;
      }

      if (e.NewValue != null)
      {
         miDataGrid.SelectionChanged += DataGrid_SelectionChanged;
         miDataGrid.Loaded += dataGrid_Loaded;
         miDataGrid.Unloaded += dataGrid_Unloaded;
      }
   }

   private static void dataGrid_Loaded(object sender, RoutedEventArgs e)
   {
      DataGrid miDataGrid = (DataGrid)sender;
      miDataGrid.SelectionChanged += DataGrid_SelectionChanged;
   }

   // ...your other code.
}

谢谢你的回答。它正在思考,但我不确定。但是我有另一个解决方案,使用Microsoft.Xaml.Behaviors.Wpf,然后我可以将事件SelectionChanged绑定为视图模型中的命令,并将属性SelectedItems作为参数传递。例如,我只需要将集合转换为列表。
using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;

namespace TabControlError.ViewModels
{
    class MainWindowViewModel : ViewModelBase
    {
        public MainWindowViewModel()
        {
            Numbers.Add(0);
            Numbers.Add(1);
            Numbers.Add(2);
            Numbers.Add(3);
        }




        private string _text;
        public string Text
        {
            get { return _text; }
            set
            {
                if (_text != value)
                {
                    _text = value;
                    RaisePropertyChangedEvent();
                }
            }
        }



        private ObservableCollection<long> _numbers = new ObservableCollection<long>();
        public ObservableCollection<long> Numbers
        {
            get { return _numbers; }
            set
            {
                if (_numbers != value)
                {
                    _numbers = value;
                    RaisePropertyChangedEvent();
                }
            }
        }

        private long? _numbersSelectedItem;
        public long? NumbersSelectedItem
        {
            get { return _numbersSelectedItem; }
            set
            {
                if (_numbersSelectedItem != value)
                {
                    _numbersSelectedItem = value;
                    RaisePropertyChangedEvent();
                }
            }
        }

        private ObservableCollection<object> _numbersSelectedItems = new ObservableCollection<object>();
        public ObservableCollection<object> NumbersSelectedItems
        {
            get { return _numbersSelectedItems; }
            set
            {
                
                _numbersSelectedItems = value;
                Text = NumbersSelectedItem?.ToString();
                RaisePropertyChangedEvent();
            }
        }
    }
}
using System.Windows;
using System.Collections;
using System.Windows.Controls;

namespace TabControlError.DependencyProperties
{
    class DataGridSelectedItemsDependencyProperty
    {
        #region SelectedItems
        ///
        /// SelectedItems Attached Dependency Property
        ///
        public static readonly DependencyProperty SelectedItemsProperty =
        DependencyProperty.RegisterAttached("SelectedItems", typeof(IList),
        typeof(DataGridSelectedItemsDependencyProperty),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
        new PropertyChangedCallback(OnSelectedItemsChanged)));

        public static IList GetSelectedItems(DependencyObject d)
        {
            return (IList)d.GetValue(SelectedItemsProperty);
        }

        public static void SetSelectedItems(DependencyObject d, IList value)
        {
            d.SetValue(SelectedItemsProperty, value);
        }

        private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            

            
            DataGrid miDataGrid = (DataGrid)d;
            miDataGrid.SelectionChanged += DataGrid_SelectionChanged;
            miDataGrid.Unloaded += dataGrid_Unloaded;
        }

        private static void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            
            DataGrid miDatagrid = (DataGrid)sender;

            //Esta variable tiene la colección del view model, o la propiedad que hace el binding al dependency property del datagrid.
            IList ModelSelectedItems = GetSelectedItems(miDatagrid);

            
            ModelSelectedItems.Clear();

            if (miDatagrid.SelectedItems != null)
            {
                foreach (var item in miDatagrid.SelectedItems)
                    ModelSelectedItems.Add(item);
            }
            SetSelectedItems(miDatagrid, ModelSelectedItems);
        }


        
        private static void dataGrid_Unloaded(object sender, RoutedEventArgs e)
        {

            DataGrid miDg = sender as DataGrid;
            miDg.SelectionChanged -= DataGrid_SelectionChanged;
            miDg.Unloaded -= dataGrid_Unloaded;
        }
        #endregion
    }
}
public class DataGridSelectedItemsDependencyProperty
{
   // ...your other code.

   private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
      DataGrid miDataGrid = (DataGrid)d;

      if (e.OldValue != null)
      {
         miDataGrid.SelectionChanged -= DataGrid_SelectionChanged;
         miDataGrid.Loaded -= dataGrid_Loaded;
         miDataGrid.Unloaded -= dataGrid_Unloaded;
      }

      if (e.NewValue != null)
      {
         miDataGrid.SelectionChanged += DataGrid_SelectionChanged;
         miDataGrid.Loaded += dataGrid_Loaded;
         miDataGrid.Unloaded += dataGrid_Unloaded;
      }
   }

   private static void dataGrid_Loaded(object sender, RoutedEventArgs e)
   {
      DataGrid miDataGrid = (DataGrid)sender;
      miDataGrid.SelectionChanged += DataGrid_SelectionChanged;
   }

   // ...your other code.
}