【问题标题】:WPF and MVVM : How to Refresh controlsWPF 和 MVVM:如何刷新控件
【发布时间】:2014-04-04 11:33:21
【问题描述】:

这是我第一个使用 WPF、MVVM 和实体框架 6 Code First 的应用程序。它是一个简单的迷你信用模拟器,由包含信用参数的左侧面板和右侧面板中的数据网格组成,用于刷新参数中所做的每个更改,它包含实体“Echeance”的集合。所以左侧面板包含文本框数据绑定到“模拟”实体中的属性,数据网格数据绑定到 ObservableCollection。

问题是,当我更改任何参数时,数据网格不会刷新更改。

在我使用 MVVM 之前,该应用程序运行良好。 代码下方:

//Entity Echeance 
 public partial class Echeance : INotifyPropertyChanged
{
    public long echeanceId { get; set; }
    public byte echNumber { get; set; }
    public double principal;
    .... //Other fields
    ...
    //Navigation to the parent

    public virtual simulation simulation { get; set; }


//Contructor with Echeance Number
  Echeance(byte n)
{
echNumber = n;
}

...


   public double MontantPrincipal
    {
        get
        {
            return principal;
        }

        set
        {
            principal = value;
            OnPropertyChanged("MontantPrincipal");
        }
    }

...Other properties
....
//
public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

}



//Entity simulation
  public partial class simulation 
{

        public long simulationId { get; set; }
         ...
        public double loyer { get; set; }

        public virtual IList<Echeance> echeancier { get; set; }
}

视图模型如下:

public class VMSimulation : ObservableObject
{
#region Fields
    simulation _simulation;
     ...        
     ObservableCollection<Echeance> _echeancier;
#endregion


    #region Constructeur
    public VMSimulation()
    {
        _simulation = new simulation();
        _echeancier = new ObservableCollection<Echeance>(_simulation.echeancier);
      //  LogIt();
    }
    #endregion

    #region Properties

    public ObservableCollection<Echeance> Echeancier
    {
        get
        {
            return _echeancier;
        }

        set
        {
            _echeancier = value;
            OnPropertyChanged("Echeancier");
        }
    }

....
  public double Loyer
    {
        get { return _simulation.loyer; }
        set
        {
            _simulation.loyer = value;
            OnPropertyChanged("Loyer");
        }
    }
...
}

XAML 只是我有刷新问题的字段

<viblend:NumberEditor x:Name="txloy"    
                                  Value="{Binding Path=Loyer, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" 
                                  Grid.Column="7" Grid.Row="2" 
                                  Style="{StaticResource viBlendDecimal}" Width="72"  ToolTip="Loyer computed." IsEnabled="False"  />


<DataGrid x:Name="gridLoyers" ItemsSource="{Binding Echeancier}" 
                  AutoGenerateColumns="False" 
                  HorizontalAlignment="Stretch" 
                  VerticalAlignment="Stretch"  
                   Margin="0"
              Grid.Column="0" Grid.Row="1" CellEditEnding="gridLoyers_CellEditEnding_1"   >
               <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding NumLoy, Mode=TwoWay, StringFormat='{}{0:#}'}"   ElementStyle="{StaticResource DataGridCellRightAlignment}"        Header="N°" />
                    <DataGridTextColumn Binding="{Binding DateEcheance ,       StringFormat={}\{0:dd/MM/yyyy\}, Mode=TwoWay}"     ElementStyle="{StaticResource DataGridCellCenterAlignment}"    Header="Echéance"/>
                    <DataGridTextColumn Binding="{Binding MontantPrincipal,  StringFormat='{}{0:#.##,0}',UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"      ElementStyle="{StaticResource DataGridCellRightAlignment}"  Header="Principal" />
                    <DataGridTextColumn Binding="{Binding MontantInteret, StringFormat='{}{0:#.##,0}'}"     ElementStyle="{StaticResource DataGridCellRightAlignment}"  Header="Intérêts"/>
                    <DataGridTextColumn Binding="{Binding MontantHT, StringFormat='{}{0:#.##,0}', UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"        ElementStyle="{StaticResource DataGridCellRightAlignment}"    Header="Hors taxe"  />
                    <DataGridTextColumn Binding="{Binding MontantTVA, StringFormat='{}{0:#.##,0}'}"       ElementStyle="{StaticResource DataGridCellRightAlignment}"    Header="TVA"/>
                    <DataGridTextColumn Binding="{Binding MontantTTC, StringFormat='{}{0:#.##,0}'}"      ElementStyle="{StaticResource DataGridCellRightAlignment}"     Header="TTC"/>
                    <DataGridTextColumn Binding="{Binding Amortfin, StringFormat='{}{0:#.##,0}'}"        ElementStyle="{StaticResource DataGridCellRightAlignment}"     Header="Amortissement"/>
                    <DataGridTextColumn Binding="{Binding Encours, StringFormat='{}{0:#.##,0}'}"         ElementStyle="{StaticResource DataGridCellRightAlignment}"     Header="Encours financier"/>
                    <DataGridCheckBoxColumn Binding="{Binding Fixe, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"         ElementStyle="{StaticResource DataGridCellRightAlignment}"     Header="Figé ?"/>
                </DataGrid.Columns>
            </DataGrid>

最后是视图:

  //Constructeur de la fenêtre
    public simulationform()
    {
        InitializeComponent();
        VMSimulation vms = new VMSimulation();  //Instanciation du ViewModel Associé
        this.DataContext = vms;
        vms.ClosingRequest += (sender, e) => this.Close();
    }

datagrid 不刷新 ObservableCollection 并且“Loyer”属性不刷新。我对此进行了调试,发现“命令”工作正常,并且列表包含正确的数据,但未刷新。 当我单击任何列标题时,datagrid 中的数据将正确刷新。奇怪的行为!!!

提前致谢

【问题讨论】:

  • 要让 UI 控件更新在视图模型中所做的更改,视图模型数据对象类必须实现INotifyPropertyChanged 接口。看起来你已经这样做了,但我不能确定你的实现是否有效。
  • 试试ItemsSource="{Binding Echeancier, UpdateSourceTrigger=PropertyChanged}" 看看是否有帮助。
  • 我试过了...还是同样的问题。

标签: wpf xaml mvvm datagrid


【解决方案1】:

通过将值设置为字段,您可以绕过属性设置器以及 INotifyPropertyChange 触发器,因此在 ctor 中将值设置为属性而不是字段。

如果你的 VM 的构造函数是 Codewise:

    #region Constructeur
    public VMSimulation()
    {
        _simulation = new simulation();
        Echeancier = new ObservableCollection<Echeance>(_simulation.echeancier); // instead of _echeancier = ...
      //  LogIt();
    }
    #endregion

【讨论】:

  • 你能澄清一下吗?你的意思是我必须从 INotifyPropertyChanged 继承模拟吗?
  • 通过将值设置为您绕过 Echeancier 属性设置器的字段,因此 OnPropertyChanged("Echeancier");永远不会被调用,VM 也没有机会报告更改。
  • user3455395 :我写对了。请查看我上面的代码。我写道:_echeancier = new ObservableCollection(_simulation.echeancier); Not Echeancier = new ObservableCollection(_simulation.echeancier);
  • 您需要设置属性才能使绑定生效。只需尝试更新您的构造函数以使用属性,看看它是否会工作。
【解决方案2】:

对不起,ViewModel 中的命令代码丢失了。

public ICommand RefreshCommand
    {
        get
        {
            if (_refreshCommand == null)
                _refreshCommand = new DelegateCommand<object>(RefreshCommandExecute);
            return _refreshCommand;
        }
    }



void RefreshCommandExecute(object obj)
    {
        _simulation.RefreshEcheancier();
        //I added this line and it works fine
        Echeancier = new ObservableCollection<Echeance>(_simulation.echeancier);
    }

所以我最近添加了这一行:

Echeancier = new ObservableCollection<Echeance>(_simulation.echeancier);

并且数据网格刷新工作正常。

谢谢...

【讨论】:

    猜你喜欢
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多