问题
I would like to binding a property defined in code-behind, and another one defined in a class in the same template with datatype. Here's an example:
My class:
public class MyClass
{
public string name { get; set; }
public MyClass(string name)
{
this.name=name;
}
}
Code behind:
public string name2;
public MyView()
{
this.InitializeComponent();
name2 = "Tim";
}
<DataTemplate x:Key="MasterListViewItemTemplate" x:DataType="model:MyClass">
<StackPanel>
<TextBlock Text="{x:Bind name}"/>
<TextBlock Text="{x:Bind name2}"/>
</StackPanel>
</DataTemplate>
In this case obviously the first TextBlock has no problems. I wish the second TextBlock refers to the code-behind and not in MyClass.
How can I do ?
回答1:
You should set the second TextBlock's datacontext to be the current window. I think this can be achieved by using binding expression like this
<TextBlock DataContext="{Binding ElementName=MyView, Path=.}" Text="{x:Bind name2}" />
where MyView in the binding expression is the x:Name property of the MyView window.
EDIT(WPF): This binding should work even for ResourceDictionary entries
<TextBlock DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=.}" Text="{Binding name2}" />
And something important, i see that your example, name2 is just defined in the constructor of the window. The right way to do it should look like this.
public string name2 { get; set; }
public MyView()
{
this.InitializeComponent();
this.name2 = "Tim";
}
I hope this helps.
回答2:
Try the following:
In constructor of your CodeBehind:
public MyView()
{
this.InitializeComponent();
this.DataContext = this; //set the datacontext here
name2 = "Tim";
}
In your XAML:
<TextBlock Text="{Binding DataContext.name2, ElementName=MyView}"/>
回答3:
First your binding always looks at the DataContext of itself first and if none is specified is traverses up the tree to owner by owner until a DataContext is assigned. It then looks there for the property to bind to. Since you have put the same property name in both textblocks and haven't specified any other means of binding they are both looking for the property in the same DataContext. In other words they are both looking at your MyClass object.
To make this work you will need to tell the Binding where to look for the property by specifying the binding more discretely.
<TextBlock Text="{Binding Name2, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}" />
This is assuming your DataTemplate is used on an object that is in a MainWindow type. Play with it to get yours.
Also, you will need to change the property in the code behind to be a DependencyProperty (since it's a UIElement this is easiest.)
public string Name2
{
get { return (string)GetValue(Name2Property); }
set { SetValue(Name2Property, value); }
}
public static readonly DependencyProperty Name2Property =
DependencyProperty.Register(nameof(Name2), typeof(string), typeof(MainWindow));
If you do this your DataTemplate will bind to that value.
This is just to answer the question and help you understand it some but not how I would personally design a DataTemplate.
来源:https://stackoverflow.com/questions/41911326/binding-a-property-defined-in-code-behind-and-another-one-defined-in-a-class-in