我刚刚开始使用WPF,我正在尝试设置局部变量和标签之间的绑定。 Basicaly我想在局部变量更改时更新标签。我正在寻找解决方案,但他们都只使用文本框作为源而不仅仅是类变量,我甚至不确定它是这样工作的。所以这是我的代码。
public partial class MainWindow : Window
{
int idCounter;
public MainWindow()
{
InitializeComponent();
Binding b = new Binding();
b.Source = idCounter;
b.Mode = BindingMode.OneWay;
b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
myLabel.SetBinding(Label.ContentProperty,b);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
idCounter++;
}
}
Button确实有效,idCounter会更改值,但它不会在标签中更新,所以我猜绑定是错误的。谁能告诉我有什么问题?感谢
答案 0 :(得分:6)
如果您将课程更改为此代码,您的代码将有效...
public partial class Window1 : Window, INotifyPropertyChanged
{
private int _idCounter;
public int IdCounter
{
get { return _idCounter; }
set
{
if (value != _idCounter)
{
_idCounter = value;
OnPropertyChanged("IdCounter");
}
}
}
public Window1()
{
InitializeComponent();
myLabel.SetBinding(ContentProperty, new Binding("IdCounter"));
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
e.Handled = true;
IdCounter++;
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
您遇到的一些问题是......
窗口本身应该实现INotifyPropertyChanged,以便绑定引擎可以放置它。
IdCounter需要公开并且有一个公共getter,以便绑定引擎可以“获得”它。
您应该将DataContext设置为声明IdCounter的任何类(在本例中为MainWindow)。部分问题是绑定引擎没有DataContext。
BindingMode设置是一个红色鲱鱼,因为默认情况下Label会以这种方式绑定。
UpdateSourceTrigger是一个红色鲱鱼,因为标签的内容没有更新源属性的机制。标签的内容不像文本框,用户可以在其中键入代码需要知道的内容。当您绑定到用户无法更改的内容时,请忘记UpdateSourceTrigger,这是重要的目标属性。
处理程序应标记该事件。这是一种很好的做法,并不影响绑定。
绑定构造函数只需要路径。
此代码将为您提供预期的结果;即,单击按钮时标签会更新。在vs2013,.net 4.5上检查,编译和执行。
其他受访者表示您应该使用View Model。我同意这100%,总的来说这是一件好事。
答案 1 :(得分:4)
您希望使用属性执行此操作,以及实施INotifyPropertyChanged
,以便在属性更改时更新label
的内容。
以下是使用简单ViewModel
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:converters="clr-namespace:WpfApplication1"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Label Width="200" Height="50" Content="{Binding MyLabel}"/>
<Button Height="30" Width="100" Content="Increment" Click="Button_Click" />
</StackPanel>
</Window>
xaml.cs:
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
MainViewModel vm = new MainViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = vm;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
vm.MyLabel += 1;
}
}
}
MainViewModel.cs:
namespace WpfApplication1
{
public class MainViewModel : INotifyPropertyChanged
{
#region Members
private int _myLabel;
#endregion Members
#region Properties
public int MyLabel
{
get
{
return _myLabel;
}
set
{
_myLabel = value;
NotifyPropertyChanged("MyLabel");
}
}
#endregion Properties
public MainViewModel()
{
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
注意:理想情况下,您希望Command
使用Button
而不是Click事件处理程序
答案 2 :(得分:1)
如果您想要通过UI选择属性更改,则应在每次属性值更改时实现INotifyPropertyChanged
接口并引发事件。所以idCounter
看起来应该更像这样:
private int _idCounter;
public int idCounter
{
get { return _idCounter; }
set
{
if (_idCounter != value)
{
_idCounter = value;
OnPropertyChanged("idCounter");
}
}
}
创建对属性的绑定时,请使用Path
绑定在绑定上下文中起作用,因此您需要指定从哪里获取此Path
。最简单的方法是设置DataContext
。因此,在您的情况下,初始化应该看起来更像这样:
Binding b = new Binding("idCounter");
b.Mode = BindingMode.OneWay;
b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
myLabel.SetBinding(Label.ContentProperty, b);
DataContext = this;
正如@ d.moncada在答案中建议你应该创建专用的视图模型