我將UserControl與ItemsControl綁定爲ObservableCollection。這個ItemsControl中的DataTemplate是一個包含TextBox和Button的Grid。使用MVVM在WPF中動態添加連接UIElements
下面是一些代碼(更新):
<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
的對象。更新在上面的代碼中。
那麼,你有什麼特別的麻煩?您的集合中應該有一個視圖模型,並帶有文本的ID值。該視圖模型也會有一個'ICommand',你可以綁定到'Button.Command'屬性。相同的視圖模型可以檢查什麼是「正確的」,並相應地更改'ICommand'的'CanExecute()'值。這些都不需要訪問UI元素;它都在視圖模型中。如果您需要所有幫助,請提供一個很好的[mcve],以清楚地顯示您嘗試過的內容,並精確說明您需要哪些幫助。 –
奇怪的是,您正在使用elvis操作符,但仍未利用'nameof()'或更好的[CallerMemberName](https://msdn.microsoft.com/en-us/library/system.runtime。 compilerservices.callermembernameattribute.aspx)屬性。 – Will
就我個人而言,我會切換到使用'ICommand',因此要執行的代碼位於ViewModel中,但是如果您確實想使用'Click'方法,則可以投射該按鈕的'.DataContext':'var data =((Button)sender).DataContext as SeparatingCard;' – Rachel