为什么双向绑定不能按预期工作?

Why twoway binding doen't work as expected?

我需要一些绑定方面的帮助。双路模式根本不起作用。 我用传递给构造函数的数据填充我的 window,它工作正常。 问题是即使我使用 Twoway 绑定,我也无法重写 window 控件中输入的某些数据。 下面是我如何打开 window

    var tempInregistrare = BaseConnection.GetInregistrareById(itemSelected.InregistrareId.ToString());
                var tichet = new TichetView(new InregistrareModel { 
                    Id =tempInregistrare.Id,
                    NumeFurnizor = tempInregistrare.NumeFurnizor,
                    IdFurnizor = tempInregistrare.IdFurnizor,
                    NumeProdus = tempInregistrare.NumeProdus......
ticket.Show();

这是 window 构造函数,DataContext 设置为 self。

  public TichetView(InregistrareModel inregistrare)
  {
            InitializeComponent();
            InregistrareModel = inregistrare;
            DataContext = this;
            grdButtonsPrint.Visibility = Visibility.Visible;
   }

  public InregistrareModel InregistrareModel
        {
            get => inregistrareModel;
            set
            {
                if (value != inregistrareModel)
                {
                    inregistrareModel = value;
                    NotifyPropertyChanged();
                }
            }
        }
 public class InregistrareModel
    {
        public int Id { get; set; }
        public int IdProdus { get; set; }
        public int IdFurnizor { get; set; }
        public string NumeProdus { get; set; }
        public string NumeFurnizor { get; set; }
        public string NrAuto { get; set; }
        public string NumeSofer { get; set; }
        public double CantitateInitiala { get; set; }
        public double CantitateIesire { get; set; }
        public double Umiditate { get; set; }
        public double CantitateScazuta { get; set; }
        public double CantitateMarfa { get; set; }
        public DateTime DataIntrare { get; set; }
        public DateTime DataIesire { get; set; }
        public FurnizorModel Furnizor { get; set; }
        public int NIR { get; set; }
    }

这里是 Xaml,共 window

                <TextBlock Grid.Row="2" Grid.Column="2" VerticalAlignment="Center">Intrare</TextBlock>                
                <TextBox Grid.Row="2" Grid.Column="3" Text="{Binding InregistrareModel.CantitateInitiala}"/>
   
                
                <TextBlock Grid.Row="4" Grid.Column="2" VerticalAlignment="Center">Umiditatea (%)</TextBlock>
                <TextBox x:Name="txtUmiditate" Grid.Row="4" Grid.Column="3" IsReadOnly="False" Text="{Binding InregistrareModel.Umiditate, Mode=TwoWay}"/>   
                
                <TextBlock Grid.Row="5" Grid.Column="2" VerticalAlignment="Center">Cantitatea scazuta</TextBlock>
                <TextBox x:Name="txtCantitateScazuta" Grid.Row="5" Grid.Column="3" IsReadOnly="False" Text="{Binding InregistrareModel.CantitateScazuta, Mode=TwoWay}"/>
                
                <TextBlock Grid.Row="6" Grid.Column="2" VerticalAlignment="Center">Iesire</TextBlock>
                <TextBox Grid.Row="6" Grid.Column="3" Text="{Binding InregistrareModel.CantitateIesire}"/>
                
                <TextBlock Grid.Row="7" Grid.Column="2" VerticalAlignment="Center">Dată iesire</TextBlock>
                <TextBox Grid.Row="7" Grid.Column="3" Text="{Binding InregistrareModel.DataIesire,StringFormat='{}{0:HH:HH dd/M/yyyy}'}"/>
                
                <TextBlock Grid.Row="10" Grid.Column="2" VerticalAlignment="Center">Net</TextBlock>
                <TextBox Grid.Row="10" Grid.Column="3" Text="{Binding InregistrareModel.CantitateMarfa}"/>

除了我手动填写的第二个和第三个文本框外,所有文本框都填充了数据。 我现在无法实现的目标是从第一个文本框(InregistrareModel.CantitateInitiala)中获取数据以输入第三个(txtCantitateScazuta)一些数据并在最后一个文本框中显示结果,所以在我用这些数据更新我的数据库之后.

  1. 您应该使 ViewModel 成为一个单独的 file/class。我们称它为 TichetViewModel。这个 class 应该有 InregistrareModel。像这样:
public class TichetViewModel : ObservableObject
{
    private InregistrareModel _InregistrareModel;
    public InregistrareModel InregistrareModel
    {
        get { return _InregistrareModel; }
        set
        {
            if (value != _InregistrareModel)
            {
                _InregistrareModel = value;
                NotifyPropertyChanged();
            }
        }
    }

    public TichetViewModel()
    {
        InregistrareModel = new InregistrareModel();
    }
}

  1. 然后在后面的代码或 xaml 中设置 TichetViewDataContext

后面的代码:

TichetView.xaml.cs

public TichetView()
{
    InitializeComponent();
    DataContext = new TichetViewModel();
}

或 xaml

TichetView.xaml

<Window.DataContext>
    <local:TichetViewModel />
</Window.DataContext>

我喜欢在 xaml 中这样做,因为 Visual Studio 中的 Intellisense 会选择它并根据 classes 自动完成。

  1. InregistrareModel 的属性实施 INotifyPropertyChanged。像这样:
public class InregistrareModel : ObservableObject
{
    private int _Id;
    public int Id
    {
        get { return _Id; }
        set
        {
            if (value != _Id)
            {
                _Id = value;
                NotifyPropertyChanged();
            }
        }
    }

    private string _NumeProdus;
    public string NumeProdus
    {
        get { return _NumeProdus; }
        set
        {
            if (value != _NumeProdus)
            {
                _NumeProdus = value;
                NotifyPropertyChanged();
            }
        }
    }
}

我完全同意@Peter Boone。 您在解决方案中有很多严重的架构错误,并且有充分的理由需要完全重做。 但是,如果您没有这样的机会,请尝试实施此选项。

对于更改的字段(TextBox、TextBlock),在 Window 中声明属性。 在这些属性的主体中,实现与父容器 (InregistrereModel) 和其他属性的通信。

假设您有一个影响 CantitateScazuta 属性.

值的 CantitateInitiala 属性
    public InregistrareModel InregistrareModel
    {
        get => inregistrareModel;
        set
        {
            if (value != inregistrareModel)
            {
                inregistrareModel = value;
                NotifyPropertyChanged();
                CantitateInitiala = InregistrareModel.CantitateInitiala;
            }
        }

    public double CantitateInitiala
    {
        get => InregistrareModel.CantitateInitiala;
        set
        {
            if (value != InregistrareModel.CantitateInitiala)
            {
                InregistrareModel.CantitateInitiala = value;
                NotifyPropertyChanged();

                // Calculation of the CantitateScazuta value
                double cantSc = CantitateInitiala / 123.45;

                CantitateScazuta = cantSc;
            }
        }
    }
    public double CantitateScazuta
    {
        get => InregistrareModel.CantitateScazuta;
        set
        {
            if (value != InregistrareModel.CantitateScazuta)
            {
                InregistrareModel.CantitateScazuta = value;
                NotifyPropertyChanged();
            }
        }
    }

在 XAML 中,更改这些字段的绑定:

            <TextBlock Grid.Row="2" Grid.Column="2" VerticalAlignment="Center">Intrare</TextBlock>                
            <TextBox Grid.Row="2" Grid.Column="3" Text="{Binding CantitateInitiala}"/>

            
            <TextBlock Grid.Row="4" Grid.Column="2" VerticalAlignment="Center">Umiditatea (%)</TextBlock>
            <TextBox x:Name="txtUmiditate" Grid.Row="4" Grid.Column="3" IsReadOnly="False" Text="{Binding InregistrareModel.Umiditate, Mode=TwoWay}"/>   
            
            <TextBlock Grid.Row="5" Grid.Column="2" VerticalAlignment="Center">Cantitatea scazuta</TextBlock>
            <TextBox x:Name="txtCantitateScazuta" Grid.Row="5" Grid.Column="3" IsReadOnly="False" Text="{Binding CantitateScazuta, Mode=TwoWay}"/>

但是你需要仔细考虑属性依赖的算法,如果它们有循环依赖的话。 也就是说,不仅改变CantitateInitiala会影响CantitateScazuta的值,而且CantitateInitiala与改变CantitateScazuta之间也存在反比关系。