我无法将数据绑定到 WPF/XAML 中的局部变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13325617/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:08:24  来源:igfitidea点击:

I can't Data Bind to a local variable in WPF/XAML

c#wpfxamldata-binding

提问by mzachen

I want a textbox to display the value of a variable when I click it (an iteration of 1 to 100), I do not know what I am doing Wrong:

我想要一个文本框在我点击它时显示一个变量的值(1 到 100 的迭代),我不知道我在做什么错:

When I run the project nothing is displayed in the text box.

当我运行项目时,文本框中没有显示任何内容。

What is the best way to display variables in a text box?

在文本框中显示变量的最佳方式是什么?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace dataBindingTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        public string myText { get; set; }

        public void Button_Click_1(object sender, RoutedEventArgs e)
        {
            int i = 0;
            for (i = 0; i < 100; i++)
            {
                myText = i.ToString();
            }
        }
    }
}

XAML:

XAML:

<Window x:Class="dataBindingTest.MainWindow"
        Name="windowElement"
        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>
        <Button Content="Button" HorizontalAlignment="Left" Height="106" Margin="71,95,0,0" VerticalAlignment="Top" Width="125" Click="Button_Click_1"/>
        <TextBlock x:Name="myTextBox" HorizontalAlignment="Left" Height="106" Margin="270,95,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="187" Text= "{Binding myText, ElementName=windowElement}" />

    </Grid>
</Window>

回答by Peter Hansen

Your current myTextproperty has no way of notifying the WPF binding system when its value has changed, so the TextBlockwont be updated.

您当前的myText属性在其值更改时无法通知 WPF 绑定系统,因此TextBlock不会更新。

If you make it a dependency property instead it automatically implements change notification, and the changes to the property will be reflected in the TextBlock.

如果您将其改为依赖属性,它会自动实现更改通知,并且对属性的更改将反映在TextBlock.

So if you replace public string myText { get; set; }with all of this code it should work:

所以如果你public string myText { get; set; }用所有这些代码替换它应该可以工作:

public string myText
{
    get { return (string)GetValue(myTextProperty); }
    set { SetValue(myTextProperty, value); }
}

// Using a DependencyProperty as the backing store for myText.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty myTextProperty =
    DependencyProperty.Register("myText", typeof(string), typeof(Window1), new PropertyMetadata(null));

回答by Manolo

implement INotifyPropertyChanged:

实施INotifyPropertyChanged

public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            this.InitializeComponent();
        }

        private string _txt;
        public string txt
        {
            get
            {
                return _txt;
            }
            set
            {
                if (_txt != value)
                {
                    _txt = value;
                    OnPropertyChanged("txt");
                }
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            txt = "changed text";
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

XAML:

XAML:

<TextBox Text="{Binding txt}"/>
<Button Click="Button_Click">yes</Button>

and don't forget about adding the DataContext property of your window:

并且不要忘记添加窗口的 DataContext 属性:

<Window ... DataContext="{Binding RelativeSource={RelativeSource Self}}"/>

回答by kmatyaszek

Try this:

尝试这个:

 public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        public string myText { get; set; }

        public void Button_Click_1(object sender, RoutedEventArgs e)
        {
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += delegate
            {
                int i = 0;
                for (i = 0; i < 100; i++)
                {
                    System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke((Action)(() => { myText = i.ToString(); OnPropertyChanged("myText"); }));                    
                    Thread.Sleep(100);
                }
            };

            bw.RunWorkerAsync();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

XAML file:

XAML 文件:

  <Grid>
            <Button Content="Button" HorizontalAlignment="Left" Height="106" Margin="71,95,0,0" VerticalAlignment="Top" Width="125" Click="Button_Click_1"/>
            <TextBlock x:Name="myTextBox" 
                       HorizontalAlignment="Right" Height="106" Margin="0,95,46,0" 
                       TextWrapping="Wrap" VerticalAlignment="Top" Width="187" 
                       Text= "{Binding myText}" />

        </Grid>

回答by Krtek

You should implement INotifyPropertyChangedin your "MainWindow" so your "myTextBlock" can automatically pick up changes from your data and update.

您应该INotifyPropertyChanged在“MainWindow”中实施,以便您的“myTextBlock”可以自动从您的数据中获取更改并进行更新。

So your "MainWindow" should look like:

所以你的“MainWindow”应该是这样的:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
    }
    private string _myText;

    public string myText { 
      get{return _myText;}
      set{_myText = value;
         if(PropertyChanged!=null) PropertyChanged(this, new PropertyChangedEventArgs("myText")) ;
      }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    etc.....
}

回答by Johan Larsson

You need to make the property tell the binding that it has updated. The standard way to do this is via:

您需要让该属性告诉绑定它已更新。执行此操作的标准方法是通过:

  1. Implementing INotifyPropertyChanged
  2. Making the myText property a DependencyProperty
  3. Another maybe less used way is to raise the event manually, like this:
  1. 实施 INotifyPropertyChanged
  2. 使 myText 属性成为 DependencyProperty
  3. 另一种可能较少使用的方法是手动引发事件,如下所示:
public void Button_Click_1(object sender, RoutedEventArgs e)
{
    myText = "Clicked";
    BindingOperations.GetBindingExpressionBase(myTextBox, TextBlock.TextProperty).UpdateTarget();
}

Note that your TextBlockhas the confusing name myTextBox

请注意,您TextBlock的名称令人困惑myTextBox