我正在学习Dependency Properties
。
我在Dependency Property
中创建了UserControl
,在MainWindow
内,我创建了一个控件实例并设置了值。这可以按预期工作。
我的问题是当我尝试使用Binding
时。
所以,我的MainWindow XAML看起来像(StartTime类型是字符串)
<Window x:Class="TimeLineCanvas.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:timeline="clr-namespace:TimeLineCanvas.UserControls"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBlock Text="{Binding StartTime}" Height="100" /><!--Works binding to local property-->
<timeline:TimeLine StartTime="28/01/2015" Height="100" /><!--Works when hard coded value-->
<timeline:TimeLine StartTime="{Binding StartTime, UpdateSourceTrigger=PropertyChanged}" Height="100" /><!-- Does not display anything -->
<timeline:TimeLine x:Name="TimeLineInXaml" Height="100" /><!-- Works (value set in code behind) -->
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.ComponentModel;
namespace TimeLineCanvas
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
#region Constructors
public MainWindow()
{
InitializeComponent();
SetStartTime(DateTime.Now);
TimeLineInXaml.StartTime = _startTime;
this.DataContext = this;
}
#endregion
#region Properties
private string _startTime;
public string StartTime
{
get
{
return _startTime;
}
set
{
_startTime = value;
OnPropertyChanged("StartTime");
}
}
#endregion
#region Methods
internal void SetStartTime(DateTime dt)
{
this.StartTime = dt.ToShortDateString();
}
#endregion
#region INotifyPropertyChanged Implementation
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion INotify
}
}
我的用户控件
<UserControl x:Class="TimeLineCanvas.UserControls.TimeLine"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Canvas>
<TextBlock Text="{Binding StartTime, UpdateSourceTrigger=PropertyChanged}" />
</Canvas>
</Grid>
</UserControl>
以及我的UserControl背后的代码
using System;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
namespace TimeLineCanvas.UserControls
{
/// <summary>
/// Interaction logic for TimeLine.xaml
/// </summary>
public partial class TimeLine : UserControl, INotifyPropertyChanged
{
#region Constructor
public TimeLine()
{
InitializeComponent();
this.DataContext = this;
}
#endregion
#region Dependancy Properties
public static readonly DependencyProperty StartTimeProperty = DependencyProperty.Register(
"StartTime",
typeof(string),
typeof(TimeLine));
#endregion
#region Properties
public string StartTime
{
get { return (string)GetValue(TimeLine.StartTimeProperty); }
set
{
DateTime result;
if (!DateTime.TryParse(value, out result))
System.Diagnostics.Debug.Assert(false, "Expected a value which can be converted to a DateTime");
SetValue(TimeLine.StartTimeProperty, value);
}
}
#endregion
#region INotifyPropertyChanged Implementation
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion INotify
}
}
所以,问题很清楚,这是绑定,但我不知道如何解决这个问题!甚至我的Voodoo编程(按随机顺序尝试任何事情和所有内容)基于其他建议(例如将DataContext="{Binding RelativeSource={RelativeSource Self}}
添加到UserControl,将INotifyPropertyChanged添加到MainWindow和UserContorl)都不会影响结果。
我做错了什么,或者我想做一些不适合做的事情?
答案 0 :(得分:1)
几乎只需简化您对Binding的理解。 请记住,这里有2个装订
MainWindow使用Property StartTime实现INotify TimeLine用户控件具有DP StartTime
所以MainWindow绑定到MainWindow.cs中的StartTime属性NB Button来测试时间的变化
<Grid>
<StackPanel>
<timeline:TimeLine x:Name="myTime" StartTime="{Binding StartTime, Mode=TwoWay}" Height="100" />
<Button Content="Change Time" Width="200" Height="100" Click="Button_Click"/>
</StackPanel>
</Grid>
MainWindow的后端
public partial class MainWindow : Window, INotifyPropertyChanged
{
#region Constructors
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
Loaded += (s, args) =>
{
this.myTime.StartTime = "Some Time";
};
}
#endregion
#region Properties
private string _startTime;
public string StartTime
{
get
{
return _startTime;
}
set
{
_startTime = value;
OnPropertyChanged("StartTime");
}
}
#endregion
#region INotifyPropertyChanged Implementation
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion INotify
private void Button_Click(object sender, RoutedEventArgs e)
{
// We are changing usercontrol StartTime DP which updates or property in main //window
this.myTime.StartTime = "A new TIME";
}
}
}
UserControl(在后端绑定到DP)
<Grid>
<Canvas>
<TextBlock Text="{Binding StartTime}" />
</Canvas>
</Grid>
UserControl后端只有DP
public partial class TimeLine : UserControl
{
#region Constructor
public TimeLine()
{
InitializeComponent();
}
public string StartTime
{
get { return (string)GetValue(StartTimeProperty); }
set { SetValue(StartTimeProperty, value); }
}
// Using a DependencyProperty as the backing store for StartTime. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StartTimeProperty =
DependencyProperty.Register("StartTime", typeof(string), typeof(TimeLine), new PropertyMetadata(""));
}
现在,当您单击“更改时间”按钮时,usercontrol将更新MainWindow属性。 希望有所帮助
答案 1 :(得分:0)
您的代码有点混乱,因为您有重复的属性名称,并且在“Voodoo编程”期间显然已经测试了很多。 :)
然而,无论如何,我认为我发现了你的问题。尝试删除TimeLine
类中的以下行:
this.DataContext = this;
这不应该在控件中,而只能在MainWindow
。
<强>解释强>
在MainWindow构造函数中,将MainWindow的DataContext
设置为自身。如果未明确设置,子元素将从其父元素继承其DataContext
。因此,DataContext
的{{1}}也设置为MainWindow,这就是TextBlock
在此正常工作的原因。但是,在所有Binding
个实例中,您将TimeLine
显式设置为自身(在构造函数中),即DataContext
对象。这样,TimeLine
实例上的Binding
不会引用TimeLine
的{{1}}属性,而是引用MainWindow
中具有相同名称的属性} 控制。但是,此属性永远不会设置为任何实际值(仅绑定到自身没有意义)。因此,不显示任何内容。