У меня есть простое приложение WPF с 3 текстовыми полями, 2 из входных номеров текстовых полей, а в третьем текстовом поле отображается сумма входов при нажатии другой кнопки.Задание привязок данных в WPF
Я пришел из фона WinForms и MFC, и для меня интуитивно понятное дело - щелкнуть правой кнопкой мыши текстовые поля, открыть их свойства и указать локальные переменные для чтения данных из полей. Например, MFC имеет для этого механизм DDX.
Однако, в WPF, единственный способ указать привязку, кажется, добавляет код XAML непосредственно в App.XAML, как показано на рисунке here on MSDN. Есть ли способ создать привязку без ее кодирования вручную в XAML? XAML-кодирование кажется мне немного сложным, так как я новичок в этом.
Моя форма WPF выглядит следующим образом:
<Window x:Class="SimpleAdd.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox HorizontalAlignment="Left" Height="23" Margin="174,43,0,0" TextWrapping="Wrap" Text="{Binding dataModel.Value1}" VerticalAlignment="Top" Width="120"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="174,84,0,0" TextWrapping="Wrap" Text="{Binding dataModel.Value2}" VerticalAlignment="Top" Width="120"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="174,127,0,0" TextWrapping="Wrap" Text="{Binding dataModel.Value3}" VerticalAlignment="Top" Width="120"/>
<Button Content="Add" HorizontalAlignment="Left" Margin="393,84,0,0" VerticalAlignment="Top" Width="75" Click="OnAdd"/>
</Grid>
</Window>
Мой C# файл выглядит следующим образом:
namespace SimpleAdd
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnAdd(object sender, RoutedEventArgs e)
{
dataModel m1 = new dataModel();
m1.Value3 = m1.Value1 + m1.Value2; // BUG : All Properties are 0 even after updating the boxes.
}
}
public class dataModel
{
private int val1, val2, val3;
public int Value1
{
get {return val1;}
set { val1 = value; }
}
public int Value2
{
get { return val2; }
set { val2 = value; }
}
public int Value3
{
get { return val3; }
set { val3 = value; }
}
}
}
EDIT: Добавление реализации для INotifyPropertyChanged
namespace SimpleAdd
{
public abstract class ObservableObject : INotifyPropertyChanged
{
#region Debugging Aides
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
[DebuggerStepThrough]
public virtual void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#endregion // Debugging Aides
#region INotifyPropertyChanged Members
/// <summary>
/// Raises the PropertyChange event for the property specified
/// </summary>
/// <param name="propertyName">Property name to update. Is case-sensitive.</param>
public virtual void RaisePropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
OnPropertyChanged(propertyName);
}
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // INotifyPropertyChanged Members
}
}
Правильный способ WPF сделать это будет либо привязать все 3 текстовых поля к свойствам в модели данных, и в datamodel убедитесь, что «Value3 = Value1 + Value2', или создайте« IMultiValueConverter », передайте ему значения из TextBox1 и TextBox2 к нему, и объединить их и вернуть значение для TextBox3. XAML обычно используется для обоих этих сценариев. Если вы не пытаетесь сделать что-то правильным способом WPF, вы можете использовать код для просто 'TextBox3.Text = int.Parse (TextBox1.Text) + int.Parse (TextBox2.Text);' или но вы этого хотите :) – Rachel
@Rachel Спасибо, что показали мне веревки. Однако я еще не совсем там. Я хотел бы научиться делать правильный путь WPF, но, основываясь на новой реализации, я не думаю, что мои привязки работают, поскольку все мои свойства имеют только 0 значений. – user2654449
Честно говоря, я по-прежнему нахожу WinForms немного легче на моем мозгу, насколько способ создания пользовательских интерфейсов. Тем не менее, я бы порекомендовал вникать в MVVM, если вы еще не пробовали - вы, безусловно, получите максимальную отдачу от своего XAML! – Craig