MVVM - 绑定自定义对象 - 在UI上更新问题

时间:2013-06-24 21:25:22

标签: c# wpf mvvm

我使用自定义类来跟踪游戏中的日期,因为DateTime不允许虚构设置。我的类绑定到窗口中的Label。初始化时,它显示正常,但在我尝试推进日期时拒绝更新。在位于ViewModel中的以下属性中,消息框确认setter已触发,但该值被视为相同且永远不会调用RaisePropertyChanged()

public Date Date
{
    get { return DataManager.Data.Date; }
    set
    {
        //Messagebox will display here...
        if (DataManager.Data.Date == value)
            return;
        //...But not here
        DataManager.Data.Date = value;
        RaisePropertyChanged(() => Date);
    }
}

我已尝试取出if语句,但仍然无法更新。 我已经尝试了几种更新Date的方法,但没有一种方法有效。这是我能够完全触发setter的唯一方法(这在ViewModel中的命令中调用):

Date = Date.AddDays(1);

消息框确认这是正确更新日期(当然是在框内)。

以下是完整的Date.cs课程:

public enum Season { Light, Shadow }
public class Date : ObservableObject
{
    #region Members

    private int _day;

    #endregion

    #region Properties

    public int Year
    {
        get { return _day / 100; }
    }

    public Season Season
    {
        get { return (DayOfYear < 70) ? Season.Light : Season.Shadow; }
    }

    public int DayOfYear
    {
        get { return _day % 100; }
    }

    #endregion

    #region Construction

    public Date(int year, int day)
    {
        _day = (100 * year) + day;
    }

    #endregion

    #region Methods

    public Date AddDays(int value)
    {
        this._day += value;

        return this;
    }

    public override string ToString()
    {
        return string.Format("{0} {1}, {2}", DayOfYear, Season, Year);
    }

    #endregion
}

这是XAML,也许它会有所帮助。我尝试了不同的绑定选项;没有工作。

<Label Content="{Binding Date}"
           Grid.Row="1"
           Grid.Column="4"
           FontFamily="Pericles"
           FontSize="16"
           VerticalAlignment="Center"
           HorizontalAlignment="Right" />

此时我不知道如何在视图中更新Date。任何建议都将不胜感激。

更新:我应该提到我正在使用MVVM Light,这是ObservableObjectRaisePropertyChanged进来的地方。此外,我的ViewModel继承自MVVM Light的{ {1}}。其他绑定属性没有任何问题。

更新:根据Sniffer的建议,ViewModelBase现在显示:

AddDays

用户界面仍然没有更新。

当我打电话给...

public Date AddDays(int value)
{
    this._day += value;

    RaisePropertyChanged(() => Year);
    RaisePropertyChanged(() => Season);
    RaisePropertyChanged(() => DayOfYear);

    return this;
}

...在命令内部,Label不会更改,但MessageBox会正确显示更新日期。

更新+可能的解决方案:我已成功完成工作。

在ViewModel中:

Date = Date.AddDays(1);
RaisePropertyChanged(() => Date);
System.Windows.MessageBox.Show(Date.ToString());

...并在命令中

public string Date
{
    get { return DataManager.Data.Date.ToString(); }
}

DataManager.Data.Date.AddDay(1); RaisePropertyChanged(() => Date);

Date.cs

使用此方法不需要提升属性,public void AddDay(int value) { this._day += value; } 甚至不需要观察。鉴于这些信息,如果有人可以提出改进建议,我全都听见了。如果没有,我会用它来称呼它。

4 个答案:

答案 0 :(得分:3)

这种情况正在发生,因为尽管您的Date类实现了Observable,但它没有为PropertyChangedEvent类中的任何属性引发任何Date。因此,如果您将日期属性设置为完全为其分配一个新日期,那么您的视图将会更新:Date = new Date(2013, 69);例如,为了解决此问题,您需要为Date中的每个属性提升PropertyChangedEvent以及那些是Year, DayOfYear, Season

答案 1 :(得分:1)

问题中的代码段显示Label绑定到Date属性,而不是日期的各个属性。用户界面无法知道日期的内容发生了变化。

听起来你需要在视图模型中的某处添加RaisePropertyChanged(() => Date),但是如果没有看到更多的代码,就很难说它放在哪里。也许在致电AddDays()之后?

答案 2 :(得分:1)

您认为您的XAML代码有什么作用?

<Label Content="{Binding Date}"
           Grid.Row="1"
           Grid.Column="4"
           FontFamily="Pericles"
           FontSize="16"
           VerticalAlignment="Center"
           HorizontalAlignment="Right" />

输出会像89 Shadow 900那样正确但这样做是错误的,因为它使用了你的toString()这不是可绑定的AFAIK

但你还有其他两个选择

第一个

在日期

中创建新媒体资源
public string dateString
{
    get { return this.ToString(); }
} // don't forget to raise it in your addDate

XAML绑定部分

<Label DataContext="{Binding Date}" Content="{Binding dateString}"
       Grid.Row="1"
       Grid.Column="4"
       FontFamily="Pericles"
       FontSize="16"
       VerticalAlignment="Center"
       HorizontalAlignment="Right" />

<强>第二

使用Mutlibinding

<TextBlock DataContext="{Binding Date}">
    <TextBlock.Text>
        <MultiBinding StringFormat='{}{0} {1}, {2}'>
            <Binding Path='DayOfYear' />
            <Binding Path='Season' />
            <Binding Path='Year' />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

答案 3 :(得分:0)

DataManager.Data.Date是什么?你刚刚发布了Date类,但是在你的setter和getter中没有任何意义,所以我认为你的Data对象中有一个属性?如果是,那么请发布这个属性 - 如果这个proeprty调用onproperty在setter中你的绑定应该工作

编辑:我现在仔细阅读:)你绑定到Date类,你想看到.AddDays(1)被调用时的变化?如果你不直接绑定年,日和月,你应该尝试更新标签的datacontext。当你想在AddDays()上看到更改时,这当然不起作用 - 如果你设置一个新的Date属性,它就会起作用。

<Label DataContext="{Binding Date}" Content="{Binding .}"
       Grid.Row="1"
       Grid.Column="4"
       FontFamily="Pericles"
       FontSize="16"
       VerticalAlignment="Center"
       HorizontalAlignment="Right" />

但是如果你直接绑定到年,日和月 - 你应该在每个上调用onpropertychanged并使用多路转换器。

问题是你绑定到一个Date对象,并希望看到日期对象内的某些东西发生变化时的变化(例如,使用AddDays(1)),这种变化不像你那样工作。