C# 从Windows应用商店应用中的ItemTemplate中绑定父DataContext

C# 从Windows应用商店应用中的ItemTemplate中绑定父DataContext,c#,mvvm,windows-store-apps,winrt-xaml,attached-properties,C#,Mvvm,Windows Store Apps,Winrt Xaml,Attached Properties,在项目模板中绑定项目模板父上下文时遇到问题 有很多“变通方法”只在WPF中有效(即使用FindAncestor和AncestorType)。这是毫无疑问的,因为它在Windows应用商店应用程序中不受支持 其他解决方案建议使用ElementName。虽然这适用于Windows应用商店应用程序,但这不是一个可接受的解决方案,因为它不可能重复使用数据模板 我读过的一个解决方案是使用附加属性/附加行为,这听起来像是一种非常通用和可重用的方法。但到目前为止我还没能成功 我当前的尝试是,创建一个全局附加属

在项目模板中绑定项目模板父上下文时遇到问题

有很多“变通方法”只在WPF中有效(即使用
FindAncestor
AncestorType
)。这是毫无疑问的,因为它在Windows应用商店应用程序中不受支持

其他解决方案建议使用
ElementName
。虽然这适用于Windows应用商店应用程序,但这不是一个可接受的解决方案,因为它不可能重复使用数据模板

我读过的一个解决方案是使用附加属性/附加行为,这听起来像是一种非常通用和可重用的方法。但到目前为止我还没能成功

我当前的尝试是,创建一个全局附加属性并在
ItemTemplate
中访问它

public class GlobalProperties : DependencyObject
{
    public static object GetParentDataContext(DependencyObject obj)
    {
        return (object)obj.GetValue(ParentDataContextProperty);
    }

    public static void SetParentDataContext(DependencyObject obj, object value)
    {
        obj.SetValue(ParentDataContextProperty, value);
    }

    // Using a DependencyProperty as the backing store for ParentDataContext.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ParentDataContextProperty =
        DependencyProperty.RegisterAttached("ParentDataContext",
            typeof(object), 
            typeof(GlobalProperties), 
            new PropertyMetadata(null, ParentDataContextChanged));

    private static void ParentDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        SetParentDataContext(d, e.NewValue);
    }
}
和我的XAML(通过在ListViews XAML代码中内联DataTemplate而简化。它稍后将存储在DataTemplate.XAML文件的外部

    <ListView 
        my:GlobalProperties.ParentDataContext="{Binding}"
        ItemsSource="{Binding Questions}"
        >
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                <Setter Property="Margin" Value="0,-1,0,0" />
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(my:GlobalProperties.ParentDataContext).Site.Styling.TagBackgroundColor}">
                        <!-- Item Related DataBindings -->      
                    </Grid>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

参考上面的评论,我将给出示例代码

Main.xaml

<Page
x:Class="TempApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="using:TempApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView x:Name="MyList">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                <Setter Property="Margin" Value="0,-1,0,0" />
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="ListItemDataTemplateGrid"                           
                      HorizontalAlignment="Stretch">
                    <Grid.Resources>
                        <converter:ValueToBackgroundConverter x:Key="ValueToBackgroundConverter" BackgroundColor="{Binding BgColor}" />
                    </Grid.Resources>
                    <Grid Background="{Binding Converter={StaticResource ValueToBackgroundConverter}}">
                        <!--Your Content-->
                    </Grid>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

我认为,在这种情况下,使用dependency属性创建转换器会起作用。听起来是一种有趣的方法,但不确定它将如何工作。dependency属性绑定到特定元素。有没有工作示例?它没有完全解决我的问题。这一个绑定ItemTemplate中的值。我需要绑定ch是在绑定到页面的ViewMoldel中定义的。如果它在项中,我可以不使用转换器直接绑定它。我添加了ViewModel示例以更好地说明它
<Page
x:Class="TempApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="using:TempApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView x:Name="MyList">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                <Setter Property="Margin" Value="0,-1,0,0" />
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="ListItemDataTemplateGrid"                           
                      HorizontalAlignment="Stretch">
                    <Grid.Resources>
                        <converter:ValueToBackgroundConverter x:Key="ValueToBackgroundConverter" BackgroundColor="{Binding BgColor}" />
                    </Grid.Resources>
                    <Grid Background="{Binding Converter={StaticResource ValueToBackgroundConverter}}">
                        <!--Your Content-->
                    </Grid>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
public sealed partial class MainPage : Page
{
    public List<TempList> ListDataSource = new List<TempList>();
    public MainPage()
    {
        this.InitializeComponent();
        FillList();           
    }

    private void FillList()
    {
        ListDataSource.Clear();
        ListDataSource.Add(new TempList { BgColor = "Red" });
        ListDataSource.Add(new TempList { BgColor = "Red" });
        MyList.ItemsSource = ListDataSource;
    }
}

public class TempList
{
    public string BgColor { get; set; }
}
class ValueToBackgroundConverter : DependencyObject, IValueConverter
    {
        public string BackgroundColor
        {
            get { return (string)GetValue(BackgroundColorProperty); }
            set { SetValue(BackgroundColorProperty, value); }
        }

        public static readonly DependencyProperty BackgroundColorProperty =
         DependencyProperty.Register("BackgroundColor",
                                     typeof(string),
                                     typeof(ValueToBackgroundConverter), null
                                     );

        public object Convert(object value, System.Type targetType, object parameter, string language)
        {
//I've used static colors but you can do manipulations to convert string to color brush
            if (BackgroundColor != null)
                return new SolidColorBrush(Color.FromArgb(0xFF, 0xA3, 0xCE, 0xDC));
            else
                return new SolidColorBrush(Color.FromArgb(0xFF, 0xE3, 0xF0, 0xF4));
        }

        public object ConvertBack(object value, System.Type targetType, object parameter, string language)
        {
            throw new System.NotImplementedException();
        }
    }