开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜