【问题标题】:ObservableCollection not updated to UI when property changed属性更改时 ObservableCollection 未更新到 UI
【发布时间】:2017-11-20 16:36:04
【问题描述】:

问题:属性更改时 ObservableCollection 未更新到 UI

我的尝试

XAML 视图:

<UserControl x:Class="FlexilineDotNetGui.Flexiline.UserControls.UCRealestate"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             xmlns:translations="clr-namespace:FlexilineDotNetGui.Flexiline.Translations"
             xmlns:viewModels="clr-namespace:FlexilineDotNetGui.Flexiline.ViewModels"
             x:Name="Realestate"
             DataContext="{StaticResource vmRealestate}">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" >
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <DataGrid Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" Height="200" Margin="5"
                          ItemsSource="{Binding Panden, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False" 
                          CanUserAddRows="False" IsReadOnly="True" SelectedItem="{Binding Pand}">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="{x:Static translations:UCRealestate.RegistrationType}" Binding="{Binding RegistrationType, Mode=TwoWay}" Width="Auto"/>
                    </DataGrid.Columns>
                </DataGrid>
                <Button Grid.Column="1"  Grid.Row="0" Background="Transparent"
                        Width="20" Height="20" Padding="0" Margin="5" Command="{Binding AddPandCMD}"
                        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type viewModels:RealestateViewModel}}}">
                    <Image Source="/Flexiline;component/Resources/New_16x16.ico"/>
                </Button>
                <Button Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" 
                        Width="20" Height="20" Padding="0" Background="Transparent" Margin="5" Command="{Binding DeletePandCMD}"
                        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type viewModels:RealestateViewModel}}}">
                    <Image Source="/Flexiline;component/Resources/Delete_16x16.ico"/>
                </Button>
                <Grid Grid.Row="3" Margin="5">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Grid Grid.Row="1" Grid.Column="1" Margin="0,5">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" MaxWidth="100"/>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                        </Grid>         
                        <Label Grid.Row="2" Grid.Column="2" Content="{x:Static translations:UCRealestate.RegistrationType}" HorizontalContentAlignment="Right" VerticalAlignment="Center"/>
                        <ComboBox Grid.Row="2" Grid.Column="3" Margin="5" ItemsSource="{Binding AardInschrijving, UpdateSourceTrigger=PropertyChanged}" SelectedValue="{Binding SelectedAardInschrijving, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Description" SelectedValuePath="FlexKey"/>
                    </Grid>
                </Grid>
            </Grid>
        </Grid>
    </Grid>
</UserControl>

视图模型:

using FlexilineDotNet.SharedDomainLogic.Models.CommunicationModels;
using FlexilineDotNetGui.Domain.Controls;
using FlexilineDotNetGui.Domain.Models;
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Data;

namespace FlexilineDotNetGui.Flexiline.ViewModels
{
    public class RealestateViewModel : ANavigationPaneSubViewModel, INotifyPropertyChanged
    {
        BorgRealestate _borgRealestate = new BorgRealestate();
        ObservableCollection<BorgRealestate> ocPanden = new ObservableCollection<BorgRealestate>();
        private DomainController _controller = DomainController.GetInstance();

        public RelayCommand<object> AddPandCMD { get; private set; }
        public RelayCommand<object> DeletePandCMD { get; private set; }

        #region "properties"

        public ObservableCollection<BorgRealestate> Panden
        {
            get
            {           
                return ocPanden ?? (ocPanden = new ObservableCollection<BorgRealestate>());
            }
            set
            {
                if (ocPanden == value)
                    return;

                ocPanden = value;
                OnPropertyChanged("Panden");
            }
        }

        //public ObservableCollection<BorgRealestate> Panden { get; }


        public BorgRealestate Pand
        {
            get
            {
                return _borgRealestate ?? (_borgRealestate = new BorgRealestate());
            }
            set
            {
                if (value == _borgRealestate) return;
                _borgRealestate = value;
                OnPropertyChanged();
                OnPropertyChanged("Panden");
            }
        }


        public List<DropDownItem> AardInschrijving { get { return _controller.GetDropDownItemsByType("AardInschrijving"); } }

        private DropDownItem SelectedAardInschrijvingDI
        {
            get
            {
                DropDownItem test = _controller.GetDropDownItemsByType("AardInschrijving").FirstOrDefault(x => x.FlexKey == _borgRealestate?.RegistrationType);
                if (test == null)
                {
                    test = _controller.GetDropDownItemsByType("AardInschrijving").FirstOrDefault();
                }
                return test;
            }
            set
            {
                OnPropertyChanged();
                OnPropertyChanged("Panden");
            }
        }

        public int SelectedAardInschrijving
        {
            get
            {
                return SelectedAardInschrijvingDI.FlexKey;
            }
            set
            {
                if (value == Pand?.RegistrationType) return;
                Pand.RegistrationType = value;
                OnPropertyChanged();
                OnPropertyChanged("Panden");
            }
        }

        public string SelectedAardInschrijvingText
        {
            get
            {
                return SelectedAardInschrijvingDI.Description;
            }
        }


        #endregion

        #region "ctor"

        public RealestateViewModel()
        {
            //Panden = new ObservableCollection<BorgRealestate>();
            AddPandCMD = new RelayCommand<object>(o => AddPand());
            DeletePandCMD = new RelayCommand<object>(o => DeletePand());
        }

        #endregion

        #region "methods"

        private void AddPand()
        {
            BorgRealestate newBorgRealestate = new BorgRealestate { RegistrationType = SelectedAardInschrijving };
            Panden.Add(newBorgRealestate);      
        }

        private void DeletePand()
        {
            Panden.Remove(Pand);
        }

        #endregion
    }
}  

问题描述:

当我更新组合框值时,当我检查断点但视图中的数据网格未更新时,它会在“Panden”属性中更新。正如我在 datagrid 列中定义的那样,Oneway 和 TwoWay 都存在问题。两种模式我都试过了。

视图位于 dxnavbar 控件中,当我在导航栏项目之间切换时,视图更新正常。

编辑:

应用程序启动时,Panden 列表确实为空,我忘了提点东西......

在我看来,有一个带有按钮的数据网格,我在其中将项目添加到可观察集合中,其中一些属性作为示例自然铭文组合框值显示在数据网格中。这个按钮然后连接到一个继电器命令。那是我绑定到datagridview的集合。

property 属性的 getter 不为空,因此填充了正确的值,只有视图中的更改不会更改。

如果没有通过 UI 上提供的按钮(relaycommand)将“Pand”项添加到“Panden”集合中,则集合为 null 确实是正常的。但是,在将带有按钮的项目添加到集合后,我从组合框中更改了一个值后,de datagrid 中的“Pand”项目将不会更新。

编辑 21/11 08:54

这是添加pand的逻辑:

private void AddPand()
        {
            BorgRealestate newBorgRealestate = new BorgRealestate { RegistrationType = SelectedAardInschrijving };
            Panden.Add(newBorgRealestate);      
        }

但在我添加之后,我看到项目被添加到集合中,并且在组合框值仅在 ui 中没有更改之后,在集合中也得到更新。 (当数据网格中的行有焦点时)

【问题讨论】:

  • 也许我遗漏了一些东西,但在任何时候都没有调用 Panden 上的 setter,因此 ocPanden 只会为空,因此 Panden getter 只会返回一个空的 ObservableCollection
  • 我已经提供了一些额外的应用信息。
  • 谢谢,您能否添加将项目添加到集合中的代码?我问的原因是我想知道您是否依赖 OnPropertyChanged("Panden") 导致数据网格更新,这在某些情况下不起作用。
  • 代码是在我将项目添加到集合的地方添加的,你能告诉我为什么数据网格在某些情况下不更新吗?
  • 我的意思是您需要在问题中包含代码,以便将项目添加到集合中。

标签: c# wpf xaml datagrid


【解决方案1】:

在此代码中:

public ObservableCollection<BorgRealestate> Panden
{
    get
    {
        return ocPanden ?? (ocPanden = new ObservableCollection<BorgRealestate>());
    }

您创建了一个新集合,但此时您没有调用 OnPropertyChanged;你不应该因为在这里这样做是错误的。因此,UI 不知道您已经创建了新集合。看起来第一次调用上述 getter 是在您的 AddPand 函数中。因此,UI 永远不会收到 Panden 的 OnPropertyChanged,因此不会更新。

在你的构造函数中创建集合,你应该会发现它会更新。此外,如果从不重新创建 Panden,您可能根本不需要 setter。

在构造函数中:

Panden = new ObservableCollection<BorgRealestate>();

那么Panden属性变为:

public ObservableCollection<BorgRealestate> Panden { get; }

可以简化为:

public ObservableCollection<BorgRealestate> Panden { get; } = new ObservableCollection<BorgRealestate>();

【讨论】:

  • 在原始问题中添加了信息
  • 谢谢我更新了我的答案,现在很清楚出了什么问题
  • 现在我在数据网格中编辑所选行的集合。数据网格值列与组合框值相同。但是当我在标签之间切换时,当我切换回来时,集合会正确更新。
  • 您可能在切换选项卡时在某处调用了 OnPropertyChanged。
  • 如果这回答了您的问题,请投票并标记为答案。谢谢。
【解决方案2】:

在视图模型中:

那一小段代码就成功了:

CollectionViewSource.GetDefaultView(ocPanden).Refresh();

替换这个:

 public ObservableCollection<BorgRealestate> Panden
        {
            get
            {           
                return ocPanden ?? (ocPanden = new ObservableCollection<BorgRealestate>());
            }
            set
            {
                if (ocPanden == value)
                    return;

                ocPanden = value;
                OnPropertyChanged("Panden");
            }
        }

有了这个:

public ObservableCollection<BorgRealestate> Panden
        {
            get
            {
                if(ocPanden != null)
                {
                    CollectionViewSource.GetDefaultView(ocPanden).Refresh(); //This will do the trick
                }
                return ocPanden ?? (ocPanden = new ObservableCollection<BorgRealestate>());
            }
            set
            {
                if (ocPanden == value)
                    return;

                ocPanden = value;
                OnPropertyChanged("Panden");
            }
        }

很遗憾,我还没有找到真正的原因?

如果有人知道,请留言?

【讨论】:

    猜你喜欢
    • 2014-01-01
    • 2018-05-18
    • 1970-01-01
    • 2017-12-28
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 2020-02-11
    相关资源
    最近更新 更多