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.
}