I have a view and a view model. I have a datagrid that when I select a row, a textbox shows the value of the row. This is just to show if the selectedItems it is fired.
it works fine, but if I change to the other tab and back, it stops to work.
I am using Net 5.
My view:
<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>
My view model base:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace TabControlError
{
class ViewModelBase : INotifyPropertyChanging, INotifyPropertyChanged
{
#region INotifyPropertyChanging Members
public event PropertyChangingEventHandler PropertyChanging;
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Administrative Properties
/// <summary>
/// Whether the view model should ignore property-change events.
/// </summary>
public virtual bool IgnorePropertyChangeEvents { get; set; }
#endregion
#region Public Methods
/// <summary>
/// Raises the PropertyChanged event.
/// </summary>
/// <param name="propertyName">The name of the changed property.</param>
//NOTA: el atributo CallerMemberName no es necesario, pero permite escribir OnPropertyChanged() en lugar de
//OnPropertyChanged("SomeProperty"), por lo que se evita utilizar strings en el código.
public virtual void RaisePropertyChangedEvent([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// Raises the PropertyChanging event.
/// </summary>
/// <param name="propertyName">The name of the changing property.</param>
//NOTA: el atributo CallerMemberName no es necesario, pero permite escribir OnPropertyChanged() en lugar de
//OnPropertyChanged("SomeProperty"), por lo que se evita utilizar strings en el código.
public virtual void RaisePropertyChangingEvent(string propertyName)
{
PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
}
#endregion
}
}
My view model:
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();
}
}
}
}
My attached property:
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;
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
}
}
Why does it stop working when I change the tab in the tab control?
Thanks.