I have very interesting scenario here, look:
MainWindow XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TabControl Grid.Row="0"
Grid.Column="0"
SelectionChanged="Selector_OnSelectionChanged">
<TabItem Header="First"/>
<TabItem Header="Second"/>
</TabControl>
<ContentPresenter Grid.Column="1"
Content="{Binding SelectedUserControl}">
</ContentPresenter>
</Grid>
UserControlOne XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<DataGrid Grid.Row="0"
ItemsSource="{Binding DataSource}"
SelectedItem="{Binding SelectedItem}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<Command:EventToCommand Command="{Binding SelectionChangedCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
<Button Grid.Row="1"
Content="SetSource"
Height="50"
Command="{Binding SetSourceCommand}"/>
<Button Grid.Row="2"
Content="RemoveSource"
Height="50"
Command="{Binding RemoveSourceCommand}"/>
</Grid>
UserContolTwo XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button Grid.Row="0"
Content="SetSource"
Height="50"
Command="{Binding SetSourceCommand}"/>
<Button Grid.Row="1"
Content="RemoveSource"
Command="{Binding RemoveSourceCommand}"
Height="50"/>
</Grid>
CodeBehind:
public class GridItem
{
public String Name { get; set; }
public override string ToString()
{
return Name;
}
}
public partial class Window1 : Window, INotifyPropertyChanged
{
private List<GridItem> _items;
private GridItem _selectedItem;
private List<GridItem> _dataSource;
private readonly List<UserControl> _userControlList;
private UserControl _selectedUserControl;
public UserControl SelectedUserControl
{
get { return _selectedUserControl; }
set
{
_selectedUserControl = value;
RaisePropertyChanged("SelectedUserControl");
}
}
public GridItem SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
RaisePropertyChanged("SelectedItem");
}
}
public List<GridItem> DataSource
{
get { return _dataSource; }
set
{
_dataSource = value;
RaisePropertyChanged("DataSource");
}
}
public Window1()
{
InitializeComponent();
DataContext = this;
_items = new List<GridItem>
{
new GridItem { Name = "Igor" },
new GridItem { Name = "Vasya"},
new GridItem { Name = "Vladlen"}
};
_userControlList = new List<UserControl>
{
new UserControl1(),
new UserControl2()
};
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(String propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChanged
private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectedUserControl = _userControlList[((TabControl)sender).SelectedIndex];
}
#region SetSourceCommand
private RelayCommand<Object> _setSourceCommand;
public RelayCommand<Object> SetSourceCommand
{
get
{
return _setSourceCommand ?? (_setSourceCommand =
new RelayCommand<Object>(SetSourceMethod));
}
}
private void SetSourceMethod(Object obj)
{
DataSource = _items;
SelectedItem = _items.FirstOrDefault();
}
#endregion SetSourceCommand
#region RemoveSourceCommand
private RelayCommand<Object> _removeSourceCommand;
public RelayCommand<Object> RemoveSourceCommand
{
get
{
return _removeSourceCommand ?? (_removeSourceCommand =
new RelayCommand<Object>(RemoveSourceMethod));
}
}
private void RemoveSourceMethod(Object obj)
{
DataSource = null;
}
#endregion RemoveSourceCommand
#region SelectionChangedCommand
private RelayCommand<Object> _selectionChangedCommand;
public RelayCommand<Object> SelectionChangedCommand
{
get
{
return _selectionChangedCommand ?? (_selectionChangedCommand =
new RelayCommand<Object>(SelectionChangedMethod));
}
}
private void SelectionChangedMethod(Object obj)
{
Debug.WriteLine("Event have been rised! Selected item is {0}", ((DataGrid)obj).SelectedItem ?? "NULL");
}
#endregion RemoveSourceCommand
}
I have MainWindow
, that contains UserControl
. UserControl
is being set dinamically, so if you pick up FirstTabItem
, then UserControlOne
will be loaded and if you pick up SecondTabItem
- UserControlTwo
will be loaded into ContentPresenter
of MainWindow
.
If I click button SetSource
on FirstTabItem
(actually on UserControlOne
) - then SelectionChanged
event of DataGrid
fires as usually. But if I click button SetSource
on SecondTabItem
(actually on UserControlTwo
) - then SelectionChanged
event of DataGrid
doesn't fire at all. Despite on bouth buttons bound to the same command (SetSourceCommand
).
If buttons don't placed on other controls, for example, only on different tabitems of the same TabControl
- bouth buttons invokes SelectionChange
event. So problem really in markup, in using UserControls
.
Has anyone encoutered with that problem? How can I fix it? I don't want invoke eventhandler programmatically.
I posted all the required code here, so you can copy-paste it and try by yourself very quickly. Or I can load example project if someone interested.
Okay so here is the actual problem in your code.
The UserControl1
has a grid in which you have used the SelectedItem
Dependency Property. On this specific DP you have a Command
SelectionChangedCommand
.
In you commands SetSourceCommand
and RemoveSourceCommand
you are updating SelectedItem
of the data grid which fires the SelectionChangedCommand
because of the event SelectionChanged
.
In your UserControl2
there is no data grid nor any control which fires SelectionChanged
event to call SelectionChangedCommand
. Hence it is never executed.