从UserControl设置ItemsSourse时,不会触发WPF DataGrid SelectionChange事件

时间:2014-08-12 06:44:53

标签: wpf datagrid user-controls selectionchanged

我在这里有一个非常有趣的场景,看看:

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>

代码隐藏:

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
}

我有MainWindow,其中包含UserControlUserControl正在设置为FirstTabItem,因此,如果您选择UserControlOne,则会加载SecondTabItem,如果您选择UserControlTwo - ContentPresenter将被加载MainWindow的{​​{1}}。

如果我点击SetSource上的按钮FirstTabItem(实际上是UserControlOne) - 那么SelectionChanged DataGrid事件就会发生。但是,如果我点击SetSource上的按钮SecondTabItem(实际上在UserControlTwo上),那么SelectionChanged DataGrid事件根本不会发生。尽管bouth按钮绑定了相同的命令(SetSourceCommand)。

如果按钮没有放在其他控件上,例如,只有在相同TabControl - bouth按钮的不同tabitems上才会调用SelectionChange事件。在使用UserControls时,标记确实存在问题。

有没有人遇到过这个问题?我该如何解决?我不想以编程方式调用eventhandler。

我在这里发布了所有必需的代码,因此您可以复制粘贴它并快速自己尝试。或者,如果有人感兴趣,我可以加载示例项目。

1 个答案:

答案 0 :(得分:2)

好的,这是代码中的实际问题。

UserControl1有一个网格,您在其中使用了SelectedItem依赖项属性。在此特定DP上,您有Command SelectionChangedCommand

在您的命令SetSourceCommandRemoveSourceCommand中,由于事件SelectedItem,您正在更新SelectionChangedCommand数据网格,该网格会触发SelectionChanged

UserControl2中,没有数据网格或任何触发SelectionChanged事件的控件可以调用SelectionChangedCommand。因此它永远不会被执行。