【问题标题】:Binding a property in an ItemsControl ItemTemplate to a DP on the UserControl is not working将 ItemsControl ItemTemplate 中的属性绑定到 UserControl 上的 DP 不起作用
【发布时间】:2011-07-19 06:10:55
【问题描述】:

UserControl 有 3 个依赖属性:FormatAvailabilities、Orientation 和 FullText。 FormatAvailabilities 绑定到 ItemsControl 的 ItemsSource 属性。如果 StackPanel 位于 ItemsControl 内的 ItemsPanelTemplate 中,则方向将绑定到 Orientation 属性。 FullText 绑定到 ItemsControl 的 DataTemplate 内的两个 TextBlock 的 Visibility 属性。我正在使用两个转换器来确定要显示哪个 TextBlock:一个 BoolToVisibilityConverter 和一个 BoolToInvertedVisibilityConverter(后者是前者的反转)。我将 Visibility 属性按原样从 TextBlock(它们都是独立的)复制到 ItemsControl,它可以正常工作..

TextBlocks 上的绑定似乎无法正常工作,因为两者始终可见。由于它们都绑定在同一个属性上,但其中一个属性是倒置的,因此两者都不应该同时可见。

我在我的转换器中放置了一个断点,它从未被命中,所以我的猜测是从重复控件内部绑定到它所在的外部控件存在问题。

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>

用户控件 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>

用户控制 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();
        }
    }
}

我一定是在看东西……谢谢!

【问题讨论】:

  • 我假设您在 App.xaml 或类似文件中定义资源 BoolToVisibilityConverter 和 BoolToInvertedVisibilityConverter?使用此详细信息更新问题可能会有所帮助。
  • 您的假设是正确的 - 更新了我的问题以包含它。

标签: c# xaml windows-phone-7 c#-4.0 binding


【解决方案1】:

blog post 所述,在 Silverlight 3 中命名用户控件存在问题,Windows Phone 7 版本的 Silverlight 中也存在该问题。实际上,如果您在使用它的 XAML 中给 UserControl 一个名称(即它的父级),那么它会覆盖 UserControl 自己的 XAML 文件中给出的名称。

【讨论】:

  • 嗯,我想这是有道理的。这是否意味着没有办法让它像我发布的那样工作?
  • @Josh - 实际上这似乎是另一个问题,因为快速测试表明它确实有效(不管文档怎么说)。我更新了我的答案。
  • 我以前遇到过这个——太烦人了。
【解决方案2】:

我遇到了类似的问题,我没有绑定到 elementname,而是将绑定更改为 this

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

而且效果很好。

【讨论】:

    【解决方案3】:

    您似乎缺少 OnPropertyChanged 处理程序。

    这是我的依赖属性之一。注意更改的处理程序。

    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;
    }
    

    【讨论】:

    • PropertyMetaData 包括 PropertyChangedHandler 是可选的。我没有对这个值做任何特别的事情,所以没有必要在 PropertyChanged 事件中做任何事情。这是一个直接和直接的绑定。
    • 值得一试,看看它是否能解决问题?听起来您的依赖项属性在某些更改时不起作用 - 这应该可以解决这个问题。
    • 我确实连接了这个事件,我可以看到属性确实在变化。事实上,我将 Visibility 属性原样从 TextBlock 复制到 ItemsControl,它在那里正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    • 2012-02-08
    • 2014-09-24
    • 2011-03-07
    相关资源
    最近更新 更多