Я очень новичок в WPF и сейчас изучаю концепции связывания данных.
мой упрощенный код XAML.кроме моей проблемы (ниже) она работает нормально - быстрое и грязное размещение объектов через графический интерфейс, будет убрано после того, как сработает:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
</Grid>
<Grid Grid.Row="1">
<GroupBox Header="Change Type:" Height="95" Width="100" VerticalAlignment="Top" Margin="270,4,422,0" >
<StackPanel>
<RadioButton x:Name="RbtAdd" HorizontalAlignment="Left" Margin="5" VerticalAlignment="Top" GroupName="modGroup" Checked="ModeRadio_Checked">
<WrapPanel>
<TextBlock Text="Add" Foreground="Green"/>
</WrapPanel>
</RadioButton>
<RadioButton x:Name="RbtPull" HorizontalAlignment="Left" Margin="5" VerticalAlignment="Top" GroupName="modGroup" Checked="ModeRadio_Checked">
<WrapPanel>
<TextBlock Text="Pull" Foreground="Blue"/>
</WrapPanel>
</RadioButton>
<RadioButton x:Name="RbtModify" HorizontalAlignment="Left" Margin="5" VerticalAlignment="Top" GroupName="modGroup" Checked="ModeRadio_Checked">
<WrapPanel>
<TextBlock Text="Modify" Foreground="DarkGray"/>
</WrapPanel>
</RadioButton>
</StackPanel>
</GroupBox>
<TextBlock x:Name="txtCurStock" HorizontalAlignment="Left" Margin="330,181,0,0" TextWrapping="Wrap" Text="{Binding Path=CurrentStock}" VerticalAlignment="Top" FontSize="20" FontWeight="Bold" TextAlignment="Center"/>
<Label Content="Current stock:" HorizontalAlignment="Left" Margin="289,156,0,0" VerticalAlignment="Top"/>
<Label x:Name ="lblOperation" Content="Stock to Pull:" HorizontalAlignment="Left" Margin="507,156,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtEntry" HorizontalAlignment="Left" Height="32" Margin="489,181,0,0" TextWrapping="Wrap" TextAlignment="Center" Text="{Binding Path=ModEntry}" VerticalAlignment="Top" Width="120" FontSize="20" FontWeight="Bold" TextChanged="TxtEntry_TextChanged"/>
<Label Content="New Stock" HorizontalAlignment="Right" Margin="714,156,0,0" VerticalAlignment="Top" Width="68"/>
<TextBlock Text="{Binding Path=NewStock}" HorizontalAlignment="Right" Margin="0,186,10,0" TextAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="20" FontWeight="Bold" Width="68"/>
<TextBox x:Name="txtComment" HorizontalAlignment="Left" Height="86" Margin="289,233,0,0" TextWrapping="Wrap" Text="{Binding Path=ModEntry}" VerticalAlignment="Top" Width="493"/>
<Label Content="Comment:" HorizontalAlignment="Left" Margin="289,207,0,0" VerticalAlignment="Top"/>
<TextBlock x:Name ="txtModindicator" HorizontalAlignment="Left" Margin="433,181,0,0" TextWrapping="Wrap" Text="-" FontSize="20" FontWeight="Bold" VerticalAlignment="Top"/>
<TextBlock x:Name ="txtResindicator" HorizontalAlignment="Left" Margin="663,182,0,0" TextWrapping="Wrap" Text="=" FontSize="20" FontWeight="Bold" VerticalAlignment="Top"/>
</Grid>
</Grid>
теперь сокращенный код c #:
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace SomeWPF
{
/// <summary>
/// Interaction logic for ModifyWindow.xaml
/// </summary>
public partial class MainWindow : INotifyPropertyChanged
{
public enum Mymode
{
add,
pull,
modify
}
public Mymode mode;
public MainWindow()
{
DataContext = this;
InitializeComponent();
CurrentStock = 5;
RbtPull.IsChecked = true;
ModEntry = 1;
}
private void ModeRadio_Checked(object sender, RoutedEventArgs e)
{
if (sender != null)
{
if (sender.Equals(RbtAdd))
{
mode = Mymode.add;
txtModindicator.Text = "+";
txtComment.Text = "Add";
lblOperation.Content = "Stock to Add:";
}
else if (sender.Equals(RbtPull))
{
mode = Mymode.pull;
txtModindicator.Text = "-";
txtComment.Text = "Pull";
lblOperation.Content = "Stock to Pull:";
}
else
{
mode = Mymode.modify;
txtModindicator.Text = "~";
lblOperation.Content = "Corrected Quantity:";
txtComment.Text = "Mod";
}
TxtEntry_TextChanged(sender, null);
}
}
private void TxtEntry_TextChanged(object sender, TextChangedEventArgs e)
{
if (mode == Mymode.add)
{
NewStock = CurrentStock + ModEntry;
}
else if (mode == Mymode.pull)
{
NewStock = CurrentStock - ModEntry;
}
else
{
NewStock = ModEntry;
}
}
#region Binding Stuff
private int _newstock;
public int NewStock
{
get
{
return _newstock;
}
set
{
if (_newstock != value)
{
_newstock = value;
OnPropertyChanged();
}
}
}
private int _modentry;
public int ModEntry
{
get
{
return _modentry;
}
set
{
if (_modentry != value)
{
_modentry = value;
OnPropertyChanged();
}
}
}
private int _currentstock;
public int CurrentStock
{
get
{
return _currentstock;
}
set
{
if (_currentstock != value)
{
_currentstock = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
Таким образом, это окно представляет собой всплывающее окно в небольшой программе для хранения инвентаря, чтобы пользователи могли вводить движения инвентаря.до сих пор все нормально, и теперь я хотел сделать довольно простую часть расчета.со «старыми» формами win c # вы бы просто взяли значения и обновили свойство text результата «вручную», но, конечно, мы (I) хотим изучить новые вещи и делать вещи с привязкой данных.Код также выполняет вычисления, но триггер почему-то не тот, что я хочу.
Допустим, текущий запас равен 5 при загрузке окна, режим установлен на Pull (RbtPull) и ввод пользователя (Binding to ModEntry).) устанавливается на 1 с помощью кода.Поэтому NewStock должен иметь значение 4, которое отображается правильно.(yey) Также поле комментария (для отладки на данный момент) отображает значение ModEntry 1. пока все хорошо.
Теперь я ввожу 3 в поле Stock to Pull, но ничего не происходит.(Я хочу, чтобы он реагировал "в реальном времени").Новый Stock по-прежнему отображается как 4, комментарий по-прежнему отображается как 1. Когда я покидаю поле (и щелкаю в поле комментария) - обнаруживается изменение свойства, и поле комментария также показывает 3 (= ModEntry) - так что этоне "в реальном времени", а срабатывает только тогда, когда поле теряет фокус, но это также было бы приемлемо.
Реальная проблема заключается в том, что новый запас остается 4 и не рассчитывается.Теперь, когда я снова вхожу в поле Stock to Pull и изменяю значение, скажем, на 5, поле New Stock обновляется до 2 (то есть до значения, которое я ввел до 5-3 = 2). Перезапись поля снова 5 изменит новоеЗапас до 0. Так что он всегда «на шаг позади».
Из того, что я обнаружил, у меня есть идея, что мне нужен какой-то Binding Converter вместо моего метода вычисления вещей, но я не могудействительно найти что-нибудь подходящее и еще недостаточно знакомы с привязкой данных.Опробовал некоторые вещи уже прямо в коде переменной связывания, но ни одна из них не сработала.Если бы кто-нибудь мог намекнуть мне в правильном направлении, я был бы очень благодарен.(не нужно решение с серебряной пластиной, а просто идея, какой способ поиска (например, если какой-либо тип привязки, который я использую, имеет смысл вообще или есть что-то, что я должен добавить и т.много!
PS: конечно, если кто-то заинтересован в решении проблемы с серебряной тарелкой, я также был бы благодарен. :) - и извините за плохой английский, нет носителя языка.