【问题标题】:Update XAML Binding after a property changes属性更改后更新 XAML 绑定
【发布时间】:2014-12-01 00:56:28
【问题描述】:

我在 Windows 8.1 应用商店应用上使用 MVVM 灯。我有一个视图模型,上面有几个没有设置器的属性(它们的值来自不同的属性)。这是我的 ViewModel 的一部分:

public float TotalAmount
{
    get
    {
        if (!LineItems.Any())
            return 0.0f;

        return SubTotal + TotalFees - TotalDiscounts;

    }
}

public float SubTotal
{
    get
    {
        return !LineItems.Any() ? 0.0f : LineItems.Select(i => i.Price.Amount).Sum();
    }
}

public float TotalFees
{
    get
    {
        return !Fees.Any() ? 0.0f : Fees.Select(f => f.Amount).Sum();
    }
}

public float TotalDiscounts
{
    get
    {
        return !Discounts.Any() ? 0.0f : Discounts.Select(d => d.Amount).Sum();
    }
}

public ObservableCollection<Discount> Discounts { get; set; }

public ObservableCollection<Fee> Fees { get; set; } 

public Customer Customer { get; set; }

public ObservableCollection<OrderLineItem> LineItems { get; set; }

在 XAML 中,我绑定到这些属性中的每一个,并希望在将项目添加到 LineItems 时更新它们。

这是 XAML 的相关部分:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*" />
        <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <TextBlock Text="SubTotal:" Style="{StaticResource OrderDetailsLabel}" />
    <TextBlock Grid.Column="1" Style="{StaticResource OrderDetailsValue}"
                Text="{Binding SubTotal, Converter={StaticResource MoneyConverter}, Mode=TwoWay}" />

    <TextBlock Grid.Row="1" Text="Fees:" Style="{StaticResource OrderDetailsLabel}" />
    <TextBlock Grid.Row="1" Style="{StaticResource OrderDetailsValue}" Grid.Column="1"
                Text="{Binding TotalFees, Converter={StaticResource MoneyConverter}, Mode=TwoWay}" />

    <TextBlock Grid.Row="2" Text="Discounts:" Style="{StaticResource OrderDetailsLabel}" />
    <TextBlock Grid.Row="2" Style="{StaticResource OrderDetailsValue}" Grid.Column="1"
                Text="{Binding TotalDiscounts, Converter={StaticResource MoneyConverter}, Mode=TwoWay}" />

    <TextBlock Grid.Row="3" Text="Order Total:" Style="{StaticResource OrderDetailsLabel}" />
    <TextBlock Grid.Row="3" Style="{StaticResource OrderDetailsValue}" Grid.Column="1"
                Text="{Binding TotalAmount, Converter={StaticResource MoneyConverter}, Mode=TwoWay}" />
</Grid>

我与 LineItems 的绑定按预期工作,但通过对行项目进行数学计算填充的字段却没有。

订单项绑定按预期运行:

 <ListView ItemsSource="{Binding LineItems, Mode=TwoWay}"
                      SelectionMode="Single"
                      HorizontalAlignment="Stretch">
                <ListView.ItemContainerStyle>
                ....

如何在 LineItems 更改时更新 SubTotal、Total 等?

【问题讨论】:

    标签: xaml data-binding windows-8.1 mvvm-light


    【解决方案1】:

    很简单:

    为每个集合注册ObservableCollection&lt;T&gt;.CollectionChanged 事件。因为您想要的属性是基于集合的一些计算。

    在事件触发时提高这些属性的 OnPropertyChanged。


    如何提高 OnPropertyChanged/inotifypropertychanged 的​​示例

    MSDN: inotifypropertychanged Example

    【讨论】:

      【解决方案2】:

      在你的构造函数中是这样的:

      LineItems.CollectionChanged += (s, e) =>
      {
         RaisePropertyChanged("SubTotal");
         RaisePropertyChanged("TotalFees");
         RaisePropertyChanged("TotalDiscounts");
      }
      

      假设您的 ViewModel 实现了 INotifyPropertyChanged,并且有一个引发 PropertyChanged 事件的“RaisePropertyChanged”方法(例如,您使用 MVVM-Light 的 ViewModelBase 作为您的基类)。

      【讨论】:

        【解决方案3】:

        我最终通过在我的 AddLineItems 消息的处理程序中引发 OnPropertyChanged 事件来解决这个问题:

            public NewOrderViewModel()
            {
                //Subscribe to messages
                MessengerInstance.Register<OrderItemAdded>(this, o => AddOrderItem(o.LineItem));
                MessengerInstance.Register<SelectedCustomer>(this, c => Customer = c.Customer);
        
                Discounts = new ObservableCollection<Discount>();
                Fees = new ObservableCollection<Fee>();
                LineItems = new ObservableCollection<OrderLineItem>();
        
            }
        
            private void AddOrderItem(OrderLineItem lineItem)
            {
                //add Line Item to collection
                LineItems.Add(lineItem);
        
                //Raise events for properties derived from collection
                RaisePropertyChanged("TotalAmount");
                RaisePropertyChanged("SubTotal");
            }
        

        【讨论】:

          猜你喜欢
          • 2016-08-07
          • 2015-09-18
          • 2019-03-24
          • 1970-01-01
          • 2020-02-06
          • 2021-09-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多