(WPF / C#)绑定到方法内的对象

时间:2017-07-10 10:11:10

标签: c# wpf xaml

为了更好地理解DataContext和绑定,我试图做一个示例,其中TextBlock显示对象的属性,其中属性值由DispatcherTimer决定。但是,TextBlock不会显示任何值。

MainWindow.xaml:

<Window x:Class="SfGauge.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid DataContext="{Binding myObj, Mode=TwoWay}">
    <TextBlock Text="{Binding RandomVal}">
    </TextBlock>
</Grid>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    randomValue myObj = new randomValue();
    public MainWindow()
    {
        InitializeComponent();

        DispatcherTimer aTimer;
        aTimer = new DispatcherTimer();

        aTimer.Interval += TimeSpan.FromSeconds(1);

        aTimer.Tick += Timer_Tick;

        aTimer.Start();


    }
 private void Timer_Tick(object sender, EventArgs e)
        {
            Dispatcher.Invoke(() =>
            {

                myObj.giveRandom();
            });   
       }

}
public class randomValue : ObservableObject
{
    Random r = new Random();
    private int randomval;
    public int RandomVal { get
        {
            return randomval;
        }
        set
        {
            SetProperty(ref randomval, value);
        }
   }
    public void giveRandom()
    {
        RandomVal = r.Next(0, 100);
    }
    public randomValue()
    {
        RandomVal = 0;
    }
}

ObservableObject.cs

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
 
    protected void OnPropertyChanged([CallerMemberName] string propName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propName));
        }
    }
 
    protected bool SetProperty<T>(ref T storage, T value,
        [CallerMemberName] String propertyName = null)
    {
        if (Equals(storage, value)) return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

2 个答案:

答案 0 :(得分:0)

以编程方式将DataContext设置为myObj

public MainWindow()
{
    InitializeComponent();

    DataContext = myObj; //<--

    DispatcherTimer aTimer;
    aTimer = new DispatcherTimer();
    aTimer.Interval += TimeSpan.FromSeconds(1);
    aTimer.Tick += Timer_Tick;
    aTimer.Start();
}

这不起作用:

DataContext="{Binding myObj, Mode=TwoWay}"

您只能绑定到公共属性。如果将myObj定义为窗口类的公共属性,也可以在XAML标记中将其绑定到它:

<Grid DataContext="{Binding myObj, RelativeSource={RelativeSource AncestorType=Window}}">

答案 1 :(得分:0)

元素的DataContext基本上只是一个对象。默认值DataContext是元素父级的DataContext,例如:

myTextBlock.DataContext = myTextBloc.Parent.DataContext

这不是正确的&#34;,但它说明了DataContext如何逐渐减少。这一直到顶部元素(在这种情况下为Window)。 Window&#39; DataContext默认为null

当您尝试绑定DataContext Grid时,Binding使用DataContext的{​​{1}}来查找属性{{ 1}}。 Grid的{​​{1}}为myObj DataContext,这会使Grid无效。

为了能够绑定Window.DataContext本身的属性,您必须将null设置为自己的Binding

Window

此外:您只能绑定到属性,因此您必须将Window作为属性:

DataContext

这样做可以让你的绑定按预期工作。

或者您可以按@ mm8建议并直接设置public MainWindow() { this.DataContext = this; ... } 的{​​{1}}。