使用MVVM连接在WPF中动态添加的UIElements

时间:2016-07-19 15:12:25

标签: c# wpf mvvm

我有UserControl,ItemsControl绑定到ObservableCollection。此ItemsControl中的DataTemplate是一个包含TextBox和Button的Grid。

以下是一些代码(已更新):

<UserControl.Resources>
    <entities:SeparatingCard x:Key="IdDataSource"/>
</UserControl.Resources>
<ItemsControl ItemsSource="{Binding Cards}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <TextBox Text="{Binding Id, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" GotFocus="TextBox_GotFocus" Grid.Row="0" Grid.Column="0"/>
                <Button DataContext="{Binding Source={StaticResource IdDataSource}}" Command="{Binding Accept}" Grid.Row="0" Grid.Column="1">Accept</Button>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

在模型文件中:

public ObservableCollection<SeparatingCard> Cards { get; set; }

卡类:

class SeparatingCard : INotifyPropertyChanged
{
    private string _id;
    public string Id
    {
        get { return _id; }
        set
        {
            _id = value;
            OnPropertyChanged("Id");
        }
    }
    public ActionCommand Accept { get; }
    public SeparatingCard()
    {
        Accept = new ActionCommand(AcceptCommandExecute);
    }
    private void AcceptCommandExecute(object obj)
    {
        MessageBox.Show(Id);
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

在运行时添加卡片,我在UserControl中动态获取一个新的文本框按钮对。现在每一对我都需要做下面的事情:
- 能够检查文本框中的文本是否正确并禁用/启用适当的按钮 - 在按钮上单击从适当的文本框中获取文本并进行处理。

我希望通过MVVM完成所有这些工作。但我只能找到直接访问UI的解决方案,只实现第二项任务:

private void Button_Click(object sender, RoutedEventArgs e)
    {
        var text = (((sender as Button).Parent as Grid).Children
            .Cast<UIElement>()
            .First(x => Grid.GetRow(x) == 0 && Grid.GetColumn(x) == 0) as TextBox).Text;
        MessageBox.Show(text);
    }

更新
正如所建议的那样,我试图将ICommand逻辑移到SeparatingCard类。现在它总是返回null,我无法检查我的命令引用的SeparatingCard类的对象。更新在上面的代码中。

1 个答案:

答案 0 :(得分:1)

而不是使用Button.Click,使用Button.Command,它可以绑定到SeparatingCard中的某些命令。

请查看本教程: http://www.codeproject.com/Tips/813345/Basic-MVVM-and-ICommand-Usage-Example

然后,SeparatingCard ViewModel将包含一个可以绑定到Button.Command的ICommand对象。 因此,如果用户单击该按钮,事件将被定向到相应的SeparatingCard对象的命令。