ObservableCollection에 바인드 된 ItemsControl이있는 UserControl이 있습니다. 이 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에있는 새로운 textbox-button 쌍. 이제 각 쌍마다 다음 작업을 수행해야합니다.
- 텍스트 상자의 텍스트가 올바른지 확인하고 적절한 단추를 사용/사용하지 않도록 설정할 수 있습니다.
- 버튼을 클릭하면 해당 텍스트 상자에서 텍스트를 가져 와서 처리합니다.
MVVM을 통해이 모든 작업을 수행하고 싶습니다.
으로 내가 SeparatingCard
클래스에 ICommand
논리를 이동하려고 제안했다
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);
}
업데이트 :하지만 난 단지 직접 UI에 대한 액세스 권한 만 두 번째 작업을 구현하는 솔루션에왔다. 이제는 항상 null을 반환하고 내 명령을 참조하는 클래스 SeparatingCard
클래스의 개체를 확인할 수 없습니다. 업데이트는 위의 코드에 있습니다.
그래서 구체적으로 문제가 있습니까? 컬렉션의 뷰 모델은 텍스트의 ID 값과 함께 있어야합니다. 이 뷰 모델은 또한'Button.Command' 속성에 바인딩 할 수있는'ICommand'를 가질 것입니다. 동일한 뷰 모델은 "올바른 것"을 검사하고 그에 따라'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