问题
Im having a problem where I can't create a User Control which uses properties of an custom object when the parent has set that object to data bind.
To try an explain what I mean here is the code. Custom object:
public class MyObj
{
public string Text { get; set; }
public MyObj(string text)
{
Text = text;
}
}
User Control Code Behind:
/// <summary>
/// Interaction logic for MyControl.xaml
/// </summary>
public partial class MyControl : UserControl
{
public static readonly DependencyProperty ObjectProperty =
DependencyProperty.Register("Object", typeof (MyObj), typeof (MyControl), new PropertyMetadata(default(MyObj)));
public MyObj Object
{
get { return (MyObj) GetValue(ObjectProperty); }
set { SetValue(ObjectProperty, value); }
}
public MyControl()
{
InitializeComponent();
}
}
User control XAML:
<UserControl x:Class="Test.MyControl"
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" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TextBlock Text="{Binding Object.Text}"/>
So all I expect is for MyControl to display a TextBlock with text showing whatever string is in MyObj.Text;
If I add the control in code, without any bindings, then this works Okay e.g.
MyControl myControl = new MyControl(){ Object = new MyObj("Hello World!") };
grid.Children.Add(myControl);
However if I try to use data binding this doesn't display anything, here is the code for MainWindow.
CodeBehind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private MyObj _Object;
public MyObj Object
{
get { return _Object; }
set
{
_Object = value;
OnPropertyChanged("Object");
}
}
public MainWindow()
{
InitializeComponent();
Object = new MyObj("HELLO");
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML:
Could anyone point me in the right direction, I guess it's something to do with using relative source binding on the UserControl but I'm not sure.
Thanks
回答1:
I've personally never used a relative self binding on a UserControl, so I'm unsure if it works. You may try setting the x:Name
of your UserControl
, and use that in the binding.
<UserControl x:Class="Test.MyControl"
...
x:Name="window">
<TextBlock Text="{Binding ElementName=window, Path=Object.Text}"/>
</UserControl>
Note that if a data-binding fails to bind at runtime, you should also see a related error message in the Output window.
回答2:
it's been a long time .. but since there is a new technique i would like to post it here.
Compiled Time Binding : this is a new type of binding introduced with windows 10. this binding has a lot of performance benefits classic binding.
And the extra benefit you need not set any DataContext the Page or Control itself is the DataContext you can bind to anything in the page or Control
<UserControl x:Class="Test.MyControl"
...
x:Name="window">
<TextBlock Text="{x:Bind Object.Text}"/>
</UserControl>
But does this work perfectly as you have imagined .. No!! not as u guessed. and there is an answer to it .
Compiled time binding are by default set to OneTime as opposed to classic bindings that are se to OneWay.
so you need to explicitly set the mode to OneWay to ensure the value always updates.
<UserControl x:Class="Test.MyControl"
...
x:Name="window">
<TextBlock Text="{x:Bind Object.Text,Mode=OneWay}"/>
</UserControl>
来源:https://stackoverflow.com/questions/17955833/binding-usercontrol-to-its-own-dependencyproperty-doesnt-work