2
votes

A UserControl has 3 Dependency Properties: FormatAvailabilities, Orientation and FullText. FormatAvailabilities is bound to the ItemsSource property of an ItemsControl. Orientation is bound to the Orientation property if the StackPanel which is in the ItemsPanelTemplate within the ItemsControl. FullText is bound to the Visibility property of two TextBlocks inside the DataTemplate of the ItemsControl. I am using two converters to determine which TextBlock to show: a BoolToVisibilityConverter and a BoolToInvertedVisibilityConverter (the latter is an inversion of the former). I copied the Visibility property as-is from the TextBlock (both of them, independently) to the ItemsControl and it works correctly..

It seems that the bindings on the TextBlocks are not working properly because both are always visible. Since they are both binding on the same property but one is inverted, there should never be a possibility for both to be visible at the same time.

I put a breakpoint in my converter and it is never hit, so my guess is that there is an issue with binding from within a repeating control to the outer control in which it is housed.

App.xaml:

<common:BaseApp x:Class="xyz.App" xmlns:converters="clr-namespace:xyz.Converters;assembly=xyz">
    <common:BaseApp.RootVisual>
        <phone:PhoneApplicationFrame x:Name="RootFrame" Source="/Home.xaml"/>
    </common:BaseApp.RootVisual>

    <common:BaseApp.Resources>
        <converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
        <converters:BoolToVisibilityConverter x:Key="BoolToInvertedVisibilityConverter" IfTrue="Collapsed" IfFalse="Visible"/>
    </common:BaseApp.Resources>
</common:BaseApp>

UserControl XAML:

<UserControl 
    x:Name="FormatsControl"
    x:Class="xyz.Formats"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <ItemsControl Background="Transparent" ItemsSource="{Binding ElementName=FormatsControl, Path=FormatAvailabilities}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="{Binding ElementName=FormatsControl, Path=Orientation}"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <TextBlock Text="{Binding BindsDirectlyToSource=True}" Margin="0,0,10,0" Visibility="{Binding ElementName=FormatsControl, Path=FullText, Converter={StaticResource BoolToVisibilityConverter}}"/>
                    <TextBlock Text="{Binding Description}" Margin="0,0,10,0" Visibility="{Binding ElementName=FormatsControl, Path=FullText, Converter={StaticResource BoolToInvertedVisibilityConverter}}"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</UserControl>

UserControl CS:

namespace xyz
{
    public partial class Formats : UserControl
    {
        public static readonly DependencyProperty FormatAvailabilitiesDependencyProperty = DependencyProperty.Register("FormatAvailabilities", typeof(FormatAvailability[]), typeof(Formats), null);
        public static readonly DependencyProperty OrientationDependencyProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(Formats), new PropertyMetadata(Orientation.Horizontal));
        public static readonly DependencyProperty FullTextDependencyProperty = DependencyProperty.Register("FullText", typeof(bool), typeof(Formats), null);

        public FormatAvailability[] FormatAvailabilities
        {
            get { return (FormatAvailability[])base.GetValue(Formats.FormatAvailabilitiesDependencyProperty); }
            set { base.SetValue(Formats.FormatAvailabilitiesDependencyProperty, value); }
        }

        public Orientation Orientation
        {
            get { return (Orientation)base.GetValue(Formats.OrientationDependencyProperty); }
            set { base.SetValue(Formats.OrientationDependencyProperty, value); }
        }

        public bool FullText
        {
            get { return (bool)base.GetValue(Formats.FullTextDependencyProperty); }
            set { base.SetValue(Formats.FullTextDependencyProperty, value); }
        }

        public Formats()
        {
            InitializeComponent();
        }
    }
}

I must be over looking something...thanks!

3
I assume you're defining the resources BoolToVisibilityConverter and BoolToInvertedVisibilityConverter in App.xaml or similar? It might help to update the question with this detail. – Martin Doms
Your assumption is correct - updated my question to include that. – Josh M.

3 Answers

1
votes

There is an issue with naming UserControls in Silverlight 3 as described by this blog post, which is also present in the Windows Phone 7 version of Silverlight. Effectively, if you give the UserControl a name in the XAML where it is used (i.e. it's parent), then that overrides the name given in the UserControl's own XAML file.

1
votes

I ran into a similar problem, instead of binding to the elementname I changed the binding to this

Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}

And that works just fine.

-1
votes

Looks like you are missing the OnPropertyChanged handler.

Here is one of my dependency properties. Note the changed handler.

public ObservableCollection<ObjWithDesc> ItemsSource
{
    get 
    {
        return (ObservableCollection<ObjWithDesc>)GetValue(ItemsSourceProperty); 
    }
    set
    {
        SetValue(ItemsSourceProperty, value);
    }
}

public static readonly DependencyProperty ItemsSourceProperty =
    DependencyProperty.Register(
        "ItemsSource",
        typeof(ObservableCollection<ObjWithDesc>),
        typeof(HorizontalListBox),
        new PropertyMetadata(OnItemsSourcePropertyChanged)
    );

static void OnItemsSourcePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    ((HorizontalListBox) obj).OnItemsSourcePropertyChanged(e);
}

private void OnItemsSourcePropertyChanged(DependencyPropertyChangedEventArgs e)
{
    ObservableCollection<ObjWithDesc> objWithDescList = (ObservableCollection<ObjWithDesc>)e.NewValue;

    MainListBox.ItemsSource = objWithDescList;
}