绑定到Windows Phone上的DataTemplate的一个元素

本文关键字:一个 元素 Windows Phone 上的 DataTemplate 绑定 | 更新日期: 2023-09-27 18:04:50

简单明了:我需要将ContextMenu项的一些属性绑定到DataTemplate中它们的父项的属性。

我找不到访问它的方法,因为ElementName不起作用,RelativeSource允许我只使用SelfTemplatedParent

下面是我的代码:

<telerikPrimitives:RadDataBoundListBox Grid.Row="2"
                                       Grid.Column="0"
                                       Grid.ColumnSpan="3"
                                       ItemsSource="{Binding Transfers.Keys, Source={StaticResource TransfersManager}, Mode=OneWay}">
                <telerikPrimitives:RadDataBoundListBox.ItemTemplate>
                    <DataTemplate>
                        <toolkit:TransferControl x:Name="TransferControl"
                            Header="{Binding Converter={StaticResource TransferMonitorToDocumentTitleConverter}}"
                            IsContextMenuEnabled="False"
                            Icon="{Binding Converter={StaticResource TransferMonitorToDocumentIconUriConverter}}"
                            AutoHide="False"
                            Monitor="{Binding}"
                            Language="it-IT"
                            StatusTextBrush="Black"
                            Foreground="Black">
                            <toolkit:TransferControl.HeaderTemplate>
                                <DataTemplate>
                                    <StackPanel>
                                        <toolkit:ContextMenuService.ContextMenu>
                                            <toolkit:ContextMenu>
                                                <toolkit:MenuItem Header="item1"
                                                                  IsEnabled="{Binding Monitor Property in the TransferControl object}"
                                                                  />
                                                <toolkit:MenuItem Header="item2"/>
                                            </toolkit:ContextMenu>
                                        </toolkit:ContextMenuService.ContextMenu>
                                        <Rectangle Fill="Transparent" Height="30"/>
                                        <ContentControl Content="{Binding}"
                                                        HorizontalAlignment="Left"
                                                        VerticalAlignment="Center"
                                                        Foreground="Black" />                                        
                     </StackPanel>
                 </DataTemplate>
             </toolkit:TransferControl.HeaderTemplate>
         </toolkit:TransferControl>
     </DataTemplate>
</telerikPrimitives:RadDataBoundListBox.ItemTemplate>

我要绑定的是:

<toolkit:MenuItem Header="item1" 
                  IsEnabled="{Binding Monitor Property in the TransferControl object}"
                  />

,我想把它绑定到<toolkit:TransferControl x:Name="TransferControl" ... />对象的Monitor属性

绑定到Windows Phone上的DataTemplate的一个元素

我可以通过简单地创建一个新的UserControl来保存ListBox的内容来解决这个问题。我使用了LongListSelector。这是一个有效的解决方案。

首先是页面的XAML:
<phone:LongListSelector Margin="0,0,-12,0" ItemsSource="{Binding Items}">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <local:WindowsPhoneControl/>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

然后是UserControl。这没什么特别的,只是一个包装。

    <UserControl x:Class="PivotApp1.WindowsPhoneControl"
    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:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">
    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
        <phone:LongListSelector x:Name="TransferControl" Margin="0,0,-12,0"
                                ItemsSource="{Binding Items}"
                                toolkit:TiltEffect.IsTiltEnabled="True">
            <phone:LongListSelector.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <toolkit:ContextMenuService.ContextMenu>
                            <toolkit:ContextMenu>
                                <toolkit:MenuItem Header="item1"
                                                  IsEnabled="{Binding DataContext.Monitor, ElementName=TransferControl}"/>
                                <toolkit:MenuItem Header="item2"/>
                            </toolkit:ContextMenu>
                        </toolkit:ContextMenuService.ContextMenu>
                        <StackPanel Margin="0,0,0,17">
                            <TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                            <TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </phone:LongListSelector.ItemTemplate>
        </phone:LongListSelector>
    </Grid>
</UserControl>

使用此解决方案,在呈现列表时命中Monitor属性。打开菜单时不会被击中。当然,如果您为monitor触发propertyChanged,它将再次获得该值。

您想要绑定的属性似乎已绑定到DataContext本身。为什么不直接在HeaderTemplate中绑定它(DataContext)呢?您所需要做的就是将Header属性绑定到DataContext,而不是将其转换为其他内容,然后在HeaderTemplate中使用Converter。像这样:

<telerikPrimitives:RadDataBoundListBox.ItemTemplate>
    <DataTemplate>
        <toolkit:TransferControl x:Name="TransferControl"
                    Header="{Binding}"
                    IsContextMenuEnabled="False"
                    Icon="{Binding Converter={StaticResource TransferMonitorToDocumentIconUriConverter}}"
                    AutoHide="False"
                    Monitor="{Binding}"
                    Language="it-IT"
                    StatusTextBrush="Black"
                    Foreground="Black">
            <toolkit:TransferControl.HeaderTemplate>
                <DataTemplate>
                    <StackPanel>
                        <toolkit:ContextMenuService.ContextMenu>
                            <toolkit:ContextMenu>
                                <toolkit:MenuItem Header="item1"
                                                            IsEnabled="{Binding}"
                                                            />
                                <toolkit:MenuItem Header="item2"/>
                            </toolkit:ContextMenu>
                        </toolkit:ContextMenuService.ContextMenu>
                        <Rectangle Fill="Transparent" Height="30"/>
                        <ContentControl Content="{Binding Converter={StaticResource TransferMonitorToDocumentTitleConverter}}"
                                                HorizontalAlignment="Left"
                                                VerticalAlignment="Center"
                                                Foreground="Black" />
                    </StackPanel>
                </DataTemplate>
            </toolkit:TransferControl.HeaderTemplate>
        </toolkit:TransferControl>
    </DataTemplate>
</telerikPrimitives:RadDataBoundListBox.ItemTemplate>

顺便说一句,我认为你可能装订得太多了。绑定和转换器可能会导致糟糕的性能,有时不绑定会更快更容易。

顺便说一句,我可以问transfermonitortodocumenttitlecconverter做什么?

好像工具箱里有个bug。Header属性的getter将对象强制转换为字符串,因此,即使该属性是object类型,也只能将其设置为字符串——否则会在内部使用的getter中抛出异常。

这是一个可能的解决方案:

  1. 像这样扩展TransferControl:

    public class TransferControlFixed : TransferControl {
        public static readonly DependencyProperty HeaderFixedProperty = DependencyProperty.Register("HeaderFixed", typeof(object), typeof(TransferControlFixed), new PropertyMetadata(null));
        public object HeaderFixed {
            get {
                return GetValue(HeaderFixedProperty);
            }
            set {
                SetValue(HeaderFixedProperty, value);
            }
        }
        public override void OnApplyTemplate() {
            base.OnApplyTemplate();
            var control = (ContentControl)this.GetTemplateChild("Header");
            control.SetBinding(ContentControl.ContentProperty, new Binding() {
                Path = new PropertyPath("HeaderFixed"),
                Source = this
            });
        }
    }
    
  2. 使用TransferControlFixed代替TransferControl,绑定HeaderFixed代替Header属性