我在项目模板中绑定ItemTemplates Parent上下文时出现问题。
有很多“变通办法”只适用于WPF(即使用FindAncestor
和AncestorType
)。这是不可能的,因为Windows Store应用程序不支持它。
其他解决方案建议使用ElementName
。虽然这适用于Windows应用商店应用,但它不是一个可接受的解决方案,因为它无法重复使用DataTemplates。
我读到的一个解决方案是使用附加属性/附加行为,这听起来像是要走的路,是一种非常通用且可重复使用的方法。但到目前为止,我无法使其发挥作用。
我目前的尝试是创建一个全局附加属性并在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>
my
是我的GlobalProperties
定义的命名空间。
当我在ParentDataContextChanged
中有一个断点时,它肯定是用DataContext调用的。但我无法让XAML代码读取它。 Background
Xaml属性始终为空,背景始终为白色(TagBackgroundColor
属性中保存的颜色为红色)。
有人知道代码/尝试有什么问题吗?
更新
此外Background="{Binding RelativeSource={RelativeSource Self}, Path=(my:GlobalProperties.ParentDataContext).Site.Styling.TagBackgroundColor}"
也不起作用,因为大多数网站都会显示此类案例的附加属性。
更新2 ViewModel的示例以便更好地说明
public class QuestionsViewModel : ViewModel
{
// Site.Styling.BackgroundColor to be bound to certain ItemTemplate
// Properties, but don't have access to it from the ItemTemplate
// because it has the context of one item from Questions
public Site Site { get; set; };
// Questions bound to ListView.DataSource > becomes Item's DataContext
public IEnumerable<Question> Questions { get; set; };
}
public class Site
{
public Style Styling { get; set; }
}
public class Style
{
public string ForegroundColor { get; set; }
public string BackgroundColor { get; set; }
public string LinkColor { get; set; }
}
答案 0 :(得分:0)
参考上述评论,我正在提供示例代码。
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>
Main.xaml.cs
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; }
}
ValueToBackgroundConverter.cs
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();
}
}