gpt4 book ai didi

silverlight - GUI/ View 不会注意到 View 模型的变化。谁应该通知?

转载 作者:行者123 更新时间:2023-12-03 10:40:02 24 4
gpt4 key购买 nike

我对 Silverlight 比较陌生,并且对通知机制有疑问。我的解决方案是这样堆叠的 MVVM 应用程序:

查看 包含一个绑定(bind)到viewmodel中一个集合的RadGridView,数据是一个entitycollection。 GridView 的 SelectedItem 绑定(bind)到 viewmodel 中的相应属性。

查看型号
保存 GridView 绑定(bind)到的下面的属性并实现 INotifyPropertyChanged。
•SelectList - 一个继承ObservableCollection 的实体集合。当 SelectList 被设置时,它会运行一个通知调用。
•SelectedItem - 一个也为自己的属性实现INotifyPropertyChanged 的​​实体。设置 SelectedItem 后,它会运行通知调用。

我的问题是,谁应该发出通知调用,以便 GridView 知道值已更改?有时,实体中的属性会直接在 View 模型中以编程方式设置。就目前而言,尽管属性正确获取了新值,但 GUI 中没有发生任何事情。

问候, 克拉斯

-- 使用代码更新 --------------

看法

<UserControl 
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
x:Class="X.Y.Z.MonthReport.MonthReportView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot">
<telerik:RadGridView x:Name="MonthReportGrid"
Grid.Row="1"
ItemsSource="{Binding SelectList}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
AutoGenerateColumns="False">
<telerik:RadGridView.Columns>
<!-- The other columns have been cut out of this example -->
<telerik:GridViewDataColumn DataMemberBinding="{Binding curDate, Mode=TwoWay, TargetNullValue=''}" DataFormatString="{} {0:d}" Header="Avläst datum" UniqueName="curDate" IsVisible="True" IsReadOnly="False">
<telerik:GridViewDataColumn.CellEditTemplate>
<DataTemplate>
<telerik:RadDateTimePicker SelectedValue="{Binding curDate, Mode=TwoWay, TargetNullValue=''}" InputMode="DatePicker" DateTimeWatermarkContent="ÅÅÅÅ-MM-DD" />
</DataTemplate>
</telerik:GridViewDataColumn.CellEditTemplate>
</telerik:GridViewDataColumn>
<telerik:GridViewDataColumn DataMemberBinding="{Binding curValue, Mode=TwoWay, TargetNullValue=''}" Header="Avläst värde" UniqueName="curValue" IsVisible="True" IsReadOnly="False" />
</telerik:RadGridView>
</Grid>
</UserControl>

查看.CS
using System;
using System.Collections.Generic;
using System.Windows.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Windows.Controls;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;


namespace X.Y.Z.MonthReport
{

public partial class MonthReportView : UserControl, IMonthReportView
{
/// <summary>
/// ViewModel attached to the View
/// </summary>
public IMonthReportViewModel Model
{
get { return this.DataContext as IMonthReportViewModel; }
set { this.DataContext = value; }
}

public MonthReportView()
{
InitializeComponent();
this.MonthReportGrid.CellEditEnded += new EventHandler<GridViewCellEditEndedEventArgs>(MonthReportGrid_OnCellEditEnded);
}


public void MonthReportGrid_OnCellEditEnded(object sender, GridViewCellEditEndedEventArgs e)
{
if (e.Cell.Column.UniqueName == "curValue")
{
// ...
this.Model.SetAutomaticReadingDate();
}

if (e.Cell.Column.UniqueName == "curDate")
{
this.Model.UpdateAutomaticReadingDate();
}
}
}
}

View 模型
using System;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Prism.Commands;


namespace X.Y.Z.MonthReport
{
public class MonthReportViewModel : ViewModel<IMonthReportView>, IMonthReportViewModel
{
private readonly IEventAggregator eventAggregator;
private readonly IMonthReportService dataService;
private readonly IMonthReportController dataController;


private DateTime? _newReadingDate;
public DateTime? NewReadingDate
{
get { return _newReadingDate; }
set { _newReadingDate = value; }
}

//Holds the selected entity
private MonthReportEntity _selectedItem;
public MonthReportEntity SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem != value)
{
_selectedItem = value;
//The INotifyPropertyChanged implementation inherited from ViewModel-base.
Notify(() => this.SelectedItem);
}
}
}

//The entitycollection
private MonthReportEntityCollection _selectList;
public MonthReportEntityCollection SelectList
{
get { return _selectList; }
set
{
if (_selectList != value)
{
_selectList = value;
//The INotifyPropertyChanged implementation inherited from ViewModel-base.
Notify(() => this.SelectList);
}
}
}

public MonthReportViewModel(IMonthReportView view,
IEventAggregator eventAggregator, IMonthReportService dataService, IMonthReportController dataController)
{
this.InitializeCommands();
this.eventAggregator = eventAggregator;
this.dataController = dataController;
this.dataService = dataService;
this.View = view;
this.View.Model = this;

dataService.onGetMonthReportComplete += new EventHandler<MonthReportEventArgs>(OnGetMonthReportComplete);
dataService.onSaveMonthReportComplete += new EventHandler<MonthReportEventArgs>(OnSaveMonthReportComplete);

InitializeData();
}

public void InitializeCommands()
{
// ...
}

public void InitializeData()
{
GetMonthReport();
}

//This function is not working as I want it to.
//The gridview doesn't notice the new value.
//If a user edits the grid row, he should not need to
//add the date manually, Therefor I use this code snippet.
public void SetAutomaticReadingDate()
{
if ((NewReadingDate.HasValue) && (!SelectedItem.curDate.HasValue))
{
SelectedItem.curDate = NewReadingDate;
//The INotifyPropertyChanged implementation inherited from ViewModel-base.
Notify(() => this.SelectedItem.curDate);
}
}

public void GetMonthReport()
{
dataService.GetMonthReport();
}

public void SaveMonthReport()
{
dataService.SaveMonthReport(SelectList);
}

void OnGetMonthReportComplete(object sender, MonthReportEventArgs e)
{
// ...
}

void OnSaveMonthReportComplete(object sender, MonthReportEventArgs e)
{
// ...
}

#region ICleanable
public override void Clean()
{
base.Clean();
}
#endregion
}
}

最佳答案

如果你这样装订

<telerik:GridViewDataColumn DataMemberBinding="{Binding curValue, Mode=TwoWay, TargetNullValue=''}" Header="Avläst värde" UniqueName="curValue" IsVisible="True" IsReadOnly="False" />

您只需要查看绑定(bind)即可知道您必须在哪里调用 PropertyChanged 并且您的绑定(bind)说:

具有属性“curValue”的类必须实现 INotifyProperyChanged 才能通知 View 。
  public void SetAutomaticReadingDate()
{
if ((NewReadingDate.HasValue) && (!SelectedItem.curDate.HasValue))
{
//this is enough if the class of SelectedItem implements INotifyPropertyChanged
//and the curDate Poperty raise the event
SelectedItem.curDate = NewReadingDate;
}
}

顺便说一句,将属性命名为 curDate 的代码样式不好!它应该是 CurDate,带有 camlCase 的属性伤害了我的眼睛 :)

关于silverlight - GUI/ View 不会注意到 View 模型的变化。谁应该通知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7579288/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com