问题
The TextBlock
resides in a DataTemplate
, thus I can't refer to it by its name. So how do I bind its (e.g.) Text
property programmatically?
XAML:
<UserControl x:Class="MyNameSpace.MyCustomControl" ... >
...
<ListBox ItemsSource="{Binding Path=ItemsSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
...
</UserControl>
Code:
public partial class MyCustomControl : UserControl {
...
public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register("DataSource", typeof (IEnumerable),
typeof (MyCustomControl),
new PropertyMetadata(default(IEnumerable)));
public IEnumerable DataSource {
get { return (IEnumerable) GetValue(DataSourceProperty); }
set { SetValue(DataSourceProperty, value); }
}
public static readonly DependencyProperty MemberPathProperty =
DependencyProperty.Register("MemberPath", typeof (string),
typeof (MyCustomControl),
new PropertyMetadata(default(string)));
public string MemberPath {
get { return (string) GetValue(MemberPathProperty); }
set { SetValue(MemberPathProperty, value); }
}
...
public MyCustomControl() {
InitializeComponent();
var binding = new Binding(MemberPath);
BindingOperations.SetBinding(/*how do I refer to the TextBlock here ???*/,
TextBox.TextProperty, binding);
}
...
}
Intended usage example:
<my:MyCustomControl DataSource="{Binding Path=SomeModelCollection}" MemberPath="Name"
Where SomeModelCollection
is some data-model property like ObservableCollection<SomeModel>
(SomeModel
has a property called Name
)
回答1:
You can get TextBlock
using VisualTreeHelper
. This method will get you all TextBlockes present in Visual tree of listBoxItem:
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj)
where T : DependencyObject
{
if( depObj != null )
{
for( int i = 0; i < VisualTreeHelper.GetChildrenCount( depObj ); i++ )
{
DependencyObject child = VisualTreeHelper.GetChild( depObj, i );
if( child != null && child is T )
{
yield return (T)child;
}
foreach( T childOfChild in FindVisualChildren<T>( child ) )
{
yield return childOfChild;
}
}
}
}
Usage :
TextBlock textBlock = FindVisualChildren<TextBlock>(listBoxItem)
.FirstOrDefault();
But I would still suggest to do the binding in XAML instead of doing it in code behind.
In case ItemSource
is ObservableCollection<MyModel>
and MyModel
contains property Name
, it can be done in XAML like this:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
Since DataContext
of ListBoxItem
will be MyModel
, hence you can bind directly to Name property like mentioned above.
来源:https://stackoverflow.com/questions/21754814/how-to-programmatically-bind-a-dependency-property-of-a-control-thats-inside