Bind an element in an ItemTemplate to a value outside the ItemSource in Windows Phone 7
I have a custom UserControl
that consists of a ListBox
with a DataTemplate
.
The ListBox
gets it's source set in XAML
and the elements in the DataTemplate
gets it's values from Binding
.
My UserControl XAML looks like this:
<UserControl x:Class="Test.UserControls.TracksListBox"
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"
xmlns:converters="clr-namespace:Test.Converters"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
mc:Ignorable="d"
d:DesignHeight="480" d:DesignWidth="480"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Name="this">
<UserControl.Resources>
<converters:BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="transparent">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<CheckBox Grid.Row="0" IsChecked="{Binding Show}"/>
<ListBox Grid.Row="1" Name="List">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Top"
Margin="0 5 0 5">
<TextBlock Text="{Binding Title}"/>
<CheckBox IsChecked="{Binding ElementName=this, Path=Show}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
And the code-behind:
namespace Test.UserControls
{
public partial class TracksListBox : UserControl
{
public static readonly DependencyProperty TracksListProperty =
DependencyProperty.Register("TracksList",
typeof(List<Track>),
typeof(TracksListBox),
new PropertyMetadata(null, OnTracksListChanged));
public static readonly Dependen开发者_如何学PythoncyProperty ShowProperty =
DependencyProperty.Register("Show",
typeof(bool),
typeof(TracksListBox),
new PropertyMetadata(false));
public TracksListBox()
{
InitializeComponent();
}
public List<Track> TracksList
{
get
{
return (List<Track>)GetValue(TracksListProperty);
}
set
{
SetValue(TracksListProperty, value);
}
}
public bool Show
{
get
{
return (bool)GetValue(ShowProperty);
}
set
{
SetValue(ShowProperty, value);
}
}
private static void OnTracksListChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
(obj as TracksListBox).OnTracksListChanged((List<Track>)args.OldValue, (List<Track>)args.NewValue);
}
protected virtual void OnTracksListChanged(List<Track> oldValue, List<Track> newValue)
{
List.ItemsSource = newValue;
}
}
}
In my MainPage.xaml I use it like this:
<userControls:TracksListBox x:Name="TopTracksListBox"
TracksList="{Binding ElementName=this, Path=TopTracks}"
Show="True"/>
My problem here is that the CheckBox
inside the ListBox
DataTemplate
won't get the value from Show
. The other CheckBox
in Grid.Row="0"
though, gets the correct value... How do I bind a value from my UserControl
inside the DataTemplate
of the ListBox
?
This must be a bug, no mather what I tried the DataContext of the CheckBox always ended up being null or a Track. If you want to work around it you can add this until this gets fixed
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Top"
Margin="0 5 0 5">
<TextBlock Text="{Binding Title}"/>
<CheckBox Loaded="CheckBox_Loaded"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
and then set the Binding in code behind once it is Loaded
private void CheckBox_Loaded(object sender, RoutedEventArgs e)
{
CheckBox checkBox = sender as CheckBox;
Binding isCheckedBinding = new Binding("Show");
isCheckedBinding.Source = this;
checkBox.SetBinding(CheckBox.IsCheckedProperty, isCheckedBinding);
}
I dropped your code into a user control in an app, changed Track
to string
and didn't bind anything to the list but I still saw a checkbox displayed and the binding of Show
to the IsChecked worked for me.
精彩评论