WPF中的嵌套对象列表数据绑定

时间:2019-05-21 16:13:22

标签: c# wpf mvvm data-binding

我正在开发一个项目,该项目是Autodesk Revit程序的插件,并且在使所有数据绑定在我创建的ViewModel中正常工作时遇到了问题。我有多个元素类型类,这些类具有一些属性和参数列表。如果参数为IsReadOnly,则这些参数来自具有名称,值和布尔值的参数类。在我的WPF表单中,我有一个用于选择元素的ListBox和一个显示要编辑的参数的DataGrid。在MainViewModel中,我执行ICommand从Revit中的元素创建区域,然后为该区域创建ZoneViewModel并将其添加到名为Zones的可观察集合中。

我为每种元素类型创建了一个ViewModel,并为参数使用了通用的ParameterViewModel。我在下面提供了Zone元素的示例。

ZoneViewModel:

    public class ZoneViewModel : ViewModelBase
    {
        private Element _element;
        private EngineZone _zone;

        public EngineZone EZone;
        private ObservableCollection<ParameterViewModel> _parameters = new ObservableCollection<ParameterViewModel>();
        public ObservableCollection<ParameterViewModel> Parameters
        {
            get => _parameters;
            set => _parameters = value;
        }

        private string _elementId;
        public string ElementId
        {
            get => _elementId = EZone.ElementId;
            set => _elementId = EZone.ElementId;
        }

        private EngineParameter _name;
        public EngineParameter Name
        {
            get => _name = EZone.Name;
            set
            {
                _name = EZone.Name;
                RaiseProperty(nameof(Name));
            }
        }

        public EngineParameter Area
        {
            get => EZone.Area;
        }

        #region Default Constructor

        public ZoneViewModel(EngineZone zone)
        {
            EZone = zone;
            ElementId = zone.ElementId;

            Parameters.Add(new ParameterViewModel(EZone.Name, false));
            Parameters.Add(new ParameterViewModel(EZone.Area, true));
        }

        #endregion

ParameterViewModel:

    public class ParameterViewModel : ViewModelBase
{
    private EngineParameter _parameter;
    private bool _isReadOnly;
    public bool IsReadOnly
    {
        get => _isReadOnly;
        set => _isReadOnly = value;
    }

    public string Name
    {
        get => _parameter.Name;
    }

    public object Value
    {
        get => _parameter.Value;
        set
        {
            if (!_isReadOnly)
            {
                _parameter.Value = value;
                RaiseProperty(nameof(Value));
            }
        }
    }

    public ParameterViewModel(EngineParameter parameter, bool isReadOnly)
    {
        _parameter = parameter;
        _isReadOnly = isReadOnly;
    }
}

我遇到的问题是,更改DataGrid中参数的值时不会更新ZoneViewModel中的属性。

Before-将区域最初添加到集合中时,一切正常。

After-更改名称后,区域元素将反映更改,但ListBox中的值不会更新。

下面是数据网格和框的XAML代码。

            <!--Column 1-->

            <TextBlock Grid.Column="0" Grid.Row="0"
                       Text="Zones" VerticalAlignment="Bottom" FontSize="16" />
            <ListBox Grid.Column="0" Grid.Row="1"
                     ItemsSource="{Binding Zones}" SelectedItem="{Binding SelectedItem}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Zone "/>
                            <TextBlock Text="{Binding Path=Name.Value}"/>
                            <TextBlock Text=" : "/>
                            <TextBlock Text="{Binding Path=ElementId}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <!--Column 2-->

            <TextBlock Grid.Column="2" Grid.Row="0"
                       Text="Info" VerticalAlignment="Bottom" FontSize="16" />

            <DataGrid Grid.Column="2" Grid.Row="1" Background="White" HeadersVisibility="None"
                      ItemsSource="{Binding SelectedItem.Parameters}" AutoGenerateColumns="False">
                <DataGrid.Resources>
                    <Style TargetType="{x:Type DataGridRow}">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsReadOnly}"
                                         Value="True">
                                <Setter Property="IsEnabled"
                                        Value="False"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </DataGrid.Resources>
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding Path = Name}" IsReadOnly="True" Width="*"/>
                    <DataGridTextColumn Binding="{Binding Path = Value}" Width="*"/>
                </DataGrid.Columns>
            </DataGrid>

我的问题是为什么ListBox值不更新?是否以某种方式引用了不同的参数/属性?我曾经尝试逐步调试过程,但是我是编程新手,很难追踪出问题所在。

0 个答案:

没有答案