将同一属性绑定到多个控件的问题

时间:2015-08-21 11:56:14

标签: c# wpf mvvm

我有一个WPF窗口,如下所示:

enter image description here 这些控件像这样绑定(仅显示几个):

<TextBlock Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Text="Code"/>
<ComboBox  Grid.Column="3" Grid.Row="1" x:Name="DdlLstCardCodes" FontWeight="Bold" SelectedItem="{Binding TransactionDetails.TransactionCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,IsAsync=True}" ItemsSource ="{Binding ListCurrencyCardCodes}"/>
<TextBlock Grid.Column="5" Grid.Row="1" VerticalAlignment="Center" Text="Currency"/>
<ComboBox Grid.Column="7" Grid.Row="1" Name="DdlCurrency" SelectedIndex="0" FontWeight="Bold" SelectedItem="{Binding TransactionDetails.CurrencyCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,IsAsync=True}" ItemsSource="{Binding UsDollerTransfer.LstCountryCode}"/>

<TextBlock Grid.Column="1" Grid.Row="3"  VerticalAlignment="Center" Text="Amount"/>
<TextBox Grid.Column="3" Grid.Row="3" Text="{Binding TransactionDetails.TransactionAmount, Mode=TwoWay,StringFormat=0{0.0}, UpdateSourceTrigger=PropertyChanged}" x:Name="TextBoxAmount"/>
<TextBlock Grid.Column="5" Grid.Row="3" VerticalAlignment="Center" Text="Charges"/>
<TextBox Grid.Column="7" Grid.Row="3" Text="{Binding TransactionDetails.Charges, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,StringFormat=N3}" IsReadOnly="True" x:Name="TextBoxcharges"/>

<Button Grid.Column="1" Grid.Row="9" Background="#0199ED"  Foreground="#D9ffff" Content="+" Name="BtnAddMore" Click="BtnAddMore_OnClick" />

<ToggleButton Name="BtnProceed" Grid.Column="6" Grid.ColumnSpan="2" Grid.Row="11" Grid.RowSpan="2" Background="#0199ED"  Foreground="#D9ffff" Content="Proceed" Command="{Binding Path=ProceedCommand,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<ToggleButton Name="PrntButton" Grid.Column="2" Grid.ColumnSpan="2" Grid.Row="11" Grid.RowSpan="2" Background="#0199ED"  Foreground="#D9ffff" Content="Print Reciept" IsThreeState="True"/>

点击+按钮后,我再次使用相同的绑定生成所有这些控件,如下所示

private void BtnAddMore_OnClick(object sender, RoutedEventArgs e)
  {
       _btnCount++;
       var txBlockCode = new TextBlock {Text = "Code", VerticalAlignment = VerticalAlignment.Center};
       var ddlCardCodes = new ComboBox
       {
           FontWeight = FontWeights.Bold,
           BorderBrush = Brushes.Black,
           Name = "NewDdlCard" + _btnCount
       };
       ddlCardCodes.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("ListCurrencyCardCodes"));
       ddlCardCodes.SetBinding(Selector.SelectedItemProperty, new Binding("TransactionDetails.TransactionCode"));
       // same like other controls
 }

在更改其中一些参数(如货币,金额,费用,MSBFEE,费率)时,总计通过此计算进行了更改

private void TransactionDetails_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "CurrencyCode":
        if (string.IsNullOrEmpty(TransactionDetails.CurrencyCode)) { return; }
        var getRate= (from x in context.DbCurrencies.Where(x => x.CurrencyCode == TransactionDetails.CurrencyCode) select x).FirstOrDefault();
        TransactionDetails.CurrencyRate=1/(getRate.Rate);
        TransactionDetails.Charges=9.85;
        TransactionDetails.SubTotal = TransactionDetails.CurrencyRate * TransactionDetails.TransactionAmount;
        TransactionDetails.Total =
            Convert.ToDouble(Math.Round((((100 - TransactionDetails.Charges) / 100) * TransactionDetails.SubTotal) + Convert.ToDouble(TransactionDetails.MsbFee), 2));
        //Also some other conditions and other cases
    }
}

TransactionDetails是我的带有属性的实体(TransactionCodeCurrencyCodeTransactionAmountCurrencyRateChargesSubTotalTotal

我的问题:

  1. 由于动态生成的控件绑定到同一属性,因此在更改其中一个项目时 绑定到同一属性的项目已更改为最新更改 价值(请参阅我填写表格,如提供的图片,点击+表示如果我选择货币AUD,我将在新面板中再次插入相同的面板,然后从AUD更改为INR {1}}因为它们绑定到同一属性TransactionDetails.CurrencyCode)同样适用于每个控件。
  2. 点击继续按钮时我想要所有这些数据(意味着多个 行)保存在数据库中。但是它已经与之相提并论 属性只有插入该属性的第一个控件 数据库中。

3 个答案:

答案 0 :(得分:1)

您的问题是您的程序设计可能基于您对mvvm patern的误解

做你想要的事情以下事情

创建包含ItemsControl的视图

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <ItemsControl Grid.RowSpan="2" 
                      ItemsSource="{Binding RecieptListe, UpdateSourceTrigger=PropertyChanged}"  />
        <Button Grid.Column="0" Grid.Row="1" Background="#0199ED"  
                Foreground="#D9ffff" Content="+" Name="BtnAddMore" 
                Command="{Binding AddRecieptCommand,UpdateSourceTrigger=PropertyChanged}" />
    <ToggleButton Name="BtnProceed" Grid.Row="2" Grid.Column="0"  
                  Background="#0199ED"  Foreground="#D9ffff" Content="Proceed" 
                  Command="{Binding Path=ProceedCommand,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />

<ToggleButton Name="PrntButton" Grid.Row="2" Grid.Column="1" Background="#0199ED"  
              Foreground="#D9ffff" Content="Print Reciept" IsThreeState="True"/>

创建一个ViewModel,其ObservableCollection为RecieptVM

public class RecieptListeVM
{
    public ObservableCollection<T> RecieptListe { get; set; }

    public ICommand AddRecieptCommand { get; set; }

    public ICommand ProceedCommand { get; set; }

    public ICommand PrintCommand { get; set; }
}

此类将包含将元素添加到列表打印并开始计算的逻辑

现在您可以在ItemsControl中使用当前的Usercontrole作为Datatemplate

结果看起来像

enter image description here

答案 1 :(得分:0)

看起来您正在绑定到对象的同一个实例。如果要跟踪不同的属性实例,则需要将对象的另一个实例分配给每组控件的DataContext。因此,每当您调用BtnAddMore_OnClick事件时,除了创建额外的面板外,还需要创建另一个数据实例。

我还建议你研究一下MVVM。因为这使得从长远来看使用WPF变得容易多了。

答案 2 :(得分:0)

您不能使用相同的绑定源来存储不同的值。每个源只存储任何类型的一个实例(一个货币单位,一个数量等)。

为了相处,您应该创建一个新的存储实例,并将其绑定到新控件。这应该可以解决你的第一个问题。

单击Proceed迭代之前创建的所有实例并将其写入数据库。这应该是你的第二个问题。