问题
I am attempting to adapt a Windows Metro-style app sample slightly by binding the title text to a property defined in code-behind, but I can't seem to get it to work. Reading the blog post titled Bind from XAML to property defined in code-behind, I am trying out "Solution 1".
Here is my XAML source (simplified):
<UserControl x:Class="... .MainPage" x:Name="UserControlSelf"
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"
d:DesignHeight="768" d:DesignWidth="1366">
<Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="TitlePanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="BackButton" Click="BackButton_Click" Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="PageTitle" Text="{Binding ElementName=UserControlSelf, Path=Title}" Style="{StaticResource TitleStyle}" Grid.Column="1"/>
</Grid>
</Grid>
</UserControl>
And here is my code-behind (simplified):
public partial class MainPage
{
private string _title;
public MainPage()
{
_title = "Test";
InitializeComponent();
}
public string Title
{
get
{
return _title;
}
}
//...
}
I set a breakpoint on the line return _title;
in the getter of the Title
property. When I debug the app, I see the back button, but the title text block control is blank (no text) and the breakpoint is not triggered:
I set a breakpoint in the autogenerated C# code for the XAML file and verified that UserControlSelf
is identical to this
within InitializeComponent()
.
How do I bind the Text
of the title text block control to the Title
property defined in code-behind?
回答1:
Can't test Metro app right now, but maybe you should implement INotifyPropertyChanged
so the binding can work.
In your code behind:
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public string Title
{
get
{
return this._title;
}
set
{
if (this._title != value)
{
this._title = value;
NotifyPropertyChanged("Title");
}
}
}
Also change
_title = "Test";
to
this.Title = "Test";
回答2:
I was finally able to get it working. Instead of messing around with ElementName
and Path
, I simply set the MainPage
instance's DataContext
to an object other than the MainPage
instance that had a Title
property. I then changed the Text
attribute of the title text block to {Binding Title}
.
It does not appear to be necessary for the data context object to implement Windows.UI.Xaml.Data.INotifyPropertyChanged; however, by doing so, the binding automatically behaves like a "one way" binding.
I originally tried setting this.DataContext = this;
, but, as I found out, that does not work. If I set it to a POCO or view model instance, then the binding is established.
It would be interesting to know why this.DataContext = this;
is erroneous, but at least I can now proceed.
回答3:
I've not used Metro, but in WPF, that won't work because Title
needs to be a Dependency Property. Change your code behind like this:
public partial class MainPage
{
public static readonly DependencyProperty TitleProperty;
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
static MainPage()
{
TitleProperty= DependencyProperty.Register(
"Title",
typeof(string),
typeof(MainPage));
}
public MainPage()
{
InitializeComponent();
Title = "Test";
}
}
This caught me out yesterday, it's so easy to forget to do.
回答4:
This technique always works for me
Text="{Binding ElementName=LayoutRoot, Path=Parent.Title}"
This assumes that the user control’s child element name is “LayoutRoot” which it is by default.
来源:https://stackoverflow.com/questions/8636713/metro-why-is-binding-from-xaml-to-a-property-defined-in-code-behind-not-working