如何以编程方式绑定传入的EnemyViewModel对象的属性?
解决动态Image控件绑定ViewModel属性的问题
一、修正当前代码的绑定错误
你现在的绑定写法存在问题,new Binding("enemyViewModel.Icon")这类路径是无效的——绑定默认会从控件的DataContext中查找对应属性,而非直接引用方法内的局部变量。可以用两种方式修正:
方式1:设置Image的DataContext为传入的EnemyViewModel
private void OnNewEnemy(EnemyViewModel enemyViewModel) { Image enemyImage = new Image() { Stretch = Stretch.Fill, DataContext = enemyViewModel // 将DataContext指向传入的ViewModel对象 }; // 绑定路径直接写属性名即可 enemyImage.SetBinding(Image.SourceProperty, new Binding(nameof(EnemyViewModel.Icon))); enemyImage.SetBinding(Grid.RowProperty, new Binding(nameof(EnemyViewModel.Row))); enemyImage.SetBinding(Grid.ColumnProperty, new Binding(nameof(EnemyViewModel.Column))); locationGrid.Children.Add(enemyImage); }
方式2:直接在Binding中指定Source为EnemyViewModel
private void OnNewEnemy(EnemyViewModel enemyViewModel) { Image enemyImage = new Image() { Stretch = Stretch.Fill }; enemyImage.SetBinding(Image.SourceProperty, new Binding(nameof(EnemyViewModel.Icon)) { Source = enemyViewModel }); enemyImage.SetBinding(Grid.RowProperty, new Binding(nameof(EnemyViewModel.Row)) { Source = enemyViewModel }); enemyImage.SetBinding(Grid.ColumnProperty, new Binding(nameof(EnemyViewModel.Column)) { Source = enemyViewModel }); locationGrid.Children.Add(enemyImage); }
二、更优的MVVM方案:用ItemsControl自动管理动态元素
你提到“代码后置是动态增删的唯一方式”其实是误解,使用ItemsControl绑定ViewModel中的敌人列表才是符合MVVM规范的做法,无需手动操作Grid的Children,增删列表元素时UI会自动同步:
1. ViewModel中维护可观察集合
确保主ViewModel里有一个可观察集合:
public ObservableCollection<EnemyViewModel> Enemies { get; } = new ObservableCollection<EnemyViewModel>();
后续添加/移除敌人时,直接对这个集合操作即可,无需触发事件调用代码后置。
2. XAML中配置ItemsControl
在XAML里定义ItemsControl,指定用Grid作为布局容器,同时绑定Row、Column和Image的Source:
<ItemsControl ItemsSource="{Binding Enemies}"> <!-- 指定ItemsControl使用Grid作为布局面板 --> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Grid x:Name="locationGrid" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <!-- 设置每个Item容器的Grid.Row和Grid.Column --> <ItemsControl.ItemContainerStyle> <Style> <Setter Property="Grid.Row" Value="{Binding Row}" /> <Setter Property="Grid.Column" Value="{Binding Column}" /> </Style> </ItemsControl.ItemContainerStyle> <!-- 定义每个敌人的UI模板 --> <ItemsControl.ItemTemplate> <DataTemplate> <Image Stretch="Fill" Source="{Binding Icon}" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
这样一来,当你在ViewModel中对Enemies集合执行Add/Remove操作时,UI会自动创建/销毁对应的Image控件,既符合MVVM规范,也避免了手动操作UI带来的维护问题。
内容的提问来源于stack exchange,提问作者AuthorBrotherGames
相关产品推荐
相关产品推荐

