将标签绑定到变量

时间:2014-05-17 21:03:08

标签: c# wpf binding event-handling controls

我刚刚开始使用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会更改值,但它不会在标签中更新,所以我猜绑定是错误的。谁能告诉我有什么问题?感谢

3 个答案:

答案 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)

  1. 您无法绑定私有或字段的内容,因此将其转换为公共属性。您可以找到有关什么是有效绑定源here
  2. 的更多信息
  3. 如果您想要通过UI选择属性更改,则应在每次属性值更改时实现INotifyPropertyChanged接口并引发事件。所以idCounter看起来应该更像这样:

    private int _idCounter;
    
    public int idCounter
    {
        get { return _idCounter; }
        set
        {
            if (_idCounter != value)
            {
                _idCounter = value;
                OnPropertyChanged("idCounter");
            }
        }
    }
    
  4. 创建对属性的绑定时,请使用Path

  5. 绑定在绑定上下文中起作用,因此您需要指定从哪里获取此Path。最简单的方法是设置DataContext。因此,在您的情况下,初始化应该看起来更像这样:

    Binding b = new Binding("idCounter");
    b.Mode = BindingMode.OneWay;
    b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    
    myLabel.SetBinding(Label.ContentProperty, b);
    DataContext = this;
    
  6. 正如@ d.moncada在答案中建议你应该创建专用的视图模型