如何让WPF矩形尺寸随列表中最大Item的Size动态变化
实现WPF中DataGrid修改Item值后自动更新最大尺寸到矩形
1. 让数据实体类实现INotifyPropertyChanged
你的Item类必须实现这个接口,这样当Size属性被修改时,能主动通知ViewModel值发生了变化:
public class SizeItem : INotifyPropertyChanged { private double _size; public double Size { get => _size; set { if (_size != value) { _size = value; OnPropertyChanged(nameof(Size)); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. ViewModel使用ObservableCollection并实现INotifyPropertyChanged
用ObservableCollection存储Item集合,它会在集合元素增删时触发变更通知;ViewModel自身实现接口,用来通知UI最大尺寸的变化:
public class MainViewModel : INotifyPropertyChanged { private ObservableCollection<SizeItem> _items; public ObservableCollection<SizeItem> Items { get => _items; set { if (_items != value) { // 移除旧集合的事件监听,避免内存泄漏 if (_items != null) { foreach (var item in _items) { item.PropertyChanged -= Item_PropertyChanged; } _items.CollectionChanged -= Items_CollectionChanged; } _items = value; // 给新集合添加监听 if (_items != null) { foreach (var item in _items) { item.PropertyChanged += Item_PropertyChanged; } _items.CollectionChanged += Items_CollectionChanged; } RecalculateMaxSize(); OnPropertyChanged(nameof(Items)); } } } private double _maxSize; public double MaxSize { get => _maxSize; set { if (_maxSize != value) { _maxSize = value; OnPropertyChanged(nameof(MaxSize)); } } } public MainViewModel() { // 初始化示例数据 Items = new ObservableCollection<SizeItem> { new SizeItem { Size = 100 }, new SizeItem { Size = 150 }, new SizeItem { Size = 200 } }; } // 监听单个Item的Size属性变化 private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(SizeItem.Size)) { RecalculateMaxSize(); } } // 监听集合的增删变化 private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { // 给新增Item绑定监听 if (e.NewItems != null) { foreach (SizeItem item in e.NewItems) { item.PropertyChanged += Item_PropertyChanged; } } // 给移除Item解绑监听 if (e.OldItems != null) { foreach (SizeItem item in e.OldItems) { item.PropertyChanged -= Item_PropertyChanged; } } RecalculateMaxSize(); } // 重新计算最大Size值 private void RecalculateMaxSize() { if (Items == null || Items.Count == 0) { MaxSize = 0; return; } MaxSize = Items.Max(item => item.Size); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
3. XAML绑定配置
确保DataGrid的Size列是双向绑定,并且输入时立即更新数据源;矩形的宽高绑定到ViewModel的MaxSize:
<Window x:Class="WpfApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp" Title="MainWindow" Height="450" Width="800"> <Window.DataContext> <local:MainViewModel /> </Window.DataContext> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- 左侧DataGrid --> <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" Grid.Column="0"> <DataGrid.Columns> <DataGridTextColumn Header="Size" Binding="{Binding Size, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> </DataGrid.Columns> </DataGrid> <!-- 右侧红色矩形 --> <Grid Grid.Column="1"> <Rectangle Fill="Red" Width="{Binding MaxSize}" Height="{Binding MaxSize}" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </Grid> </Window>
关键细节说明
UpdateSourceTrigger=PropertyChanged:让DataGrid文本框在输入时立即更新数据源,实现矩形尺寸实时同步- 集合替换时的事件解绑:必须移除旧Item的监听,否则会导致内存泄漏
- 空集合判断:
RecalculateMaxSize中处理空集合场景,避免空引用异常
内容的提问来源于stack exchange,提问作者mmdn
相关产品推荐
相关产品推荐

