我正在尝试创建一个自定义用户控件,我可以在所有视图中重用它。我的BaseViewModel有一个名为ViewAlerts的属性,用于在整个应用程序中一致地显示警报(例如成功更新,请求失败等)。我能够达到我的自定义控件是可构建的并且具有绑定属性的程度,但是从不显示警报集合。我在我的基本视图模型中静态定义一些警报用于测试目的,并且无法显示警报(看起来像INotifyPropertyChanged的问题,但我的可绑定属性继承自ObservableCollection<>所以它应该自动处理我认为)。
到目前为止,这是我的自定义控件:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Resources/MMJCeoResources.xaml" />
<ResourceDictionary>
<Style TargetType="TextBlock" x:Key="AlertTextStyle">
<Setter Property="FontSize" Value="15"></Setter>
<Setter Property="Margin" Value="10" />
<Setter Property="Padding" Value="10" />
</Style>
<DataTemplate x:Key="DangerAlert">
<Grid Background="LightPink">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Border Width="10"
Height="10"
BorderBrush="DarkRed"
HorizontalAlignment="Right"
Margin="5"
Grid.Row="0">
<TextBlock Text="X" />
</Border>
<TextBlock Grid.Row="1" Text="{Binding Message}" Style="{StaticResource AlertTextStyle}" Foreground="DarkRed"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="SuccessAlert">
<Grid Background="LightGreen">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Border Width="10"
Height="10"
BorderBrush="DarkGreen"
HorizontalAlignment="Right"
Margin="5"
Grid.Row="0">
<TextBlock Text="X" />
</Border>
<TextBlock Grid.Row="1" Text="{Binding Message}" Style="{StaticResource AlertTextStyle}" Foreground="DarkGreen"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="InfoAlert">
<Grid Background="LightGreen">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Border Width="10"
Height="10"
BorderBrush="DarkGreen"
HorizontalAlignment="Right"
Margin="5"
Grid.Row="0">
<TextBlock Text="X" />
</Border>
<TextBlock Grid.Row="1" Text="{Binding Message}" Style="{StaticResource AlertTextStyle}" Foreground="DarkGreen"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="WarningAlert">
<Grid Background="LightSalmon">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Border Width="10"
Height="10"
BorderBrush="DarkOrange"
HorizontalAlignment="Right"
Margin="5"
Grid.Row="0">
<TextBlock Text="X" />
</Border>
<TextBlock Grid.Row="1" Text="{Binding Message}" Style="{StaticResource AlertTextStyle}" Foreground="DarkOrange"/>
</Grid>
</DataTemplate>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding Path=Alerts}"
ItemTemplateSelector="{StaticResource AlertDataTemplateSelector}">
</ItemsControl>
</Grid>
</UserControl>
控制的守则:
public sealed partial class AlertControl : UserControl
{
public static readonly DependencyProperty AlertsProperty = DependencyProperty.Register(
"Alerts", typeof (ObservableList<Alert>), typeof (AlertControl), new PropertyMetadata(default(ObservableList<Alert>), OnAlertsChanged));
public ObservableList<Alert> Alerts
{
get { return (ObservableList<Alert>) GetValue(AlertsProperty); }
set { SetValue(AlertsProperty, value); }
}
//I was trying to adapt another tutorial to what I was trying to accomplish but only got this far
public static void OnAlertsChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var old = e.OldValue as ObservableList<Alert>;
var me = sender as AlertControl;
if (old != null)
{
old.CollectionChanged -= me.OnAlertCollectionChanged;
}
var n = e.NewValue as ObservableList<Alert>;
if (n != null)
n.CollectionChanged += me.OnAlertCollectionChanged;
}
private void OnAlertCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Reset)
{
Alerts.Clear();
var n = e.NewItems as ObservableList<Alert>;
Alerts.AddRange(n);
}
}
public AlertControl()
{
this.InitializeComponent();
DataContext = this;
}
}
示例实现:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<TextBlock Style="{StaticResource PageTitle}" Text="User Information" />
<controls:AlertControl Alerts="{Binding ViewAlerts}" />
在此实现中,ViewAlerts属性中有4个静态定义的警报,因此我知道应该显示的值。
答案 0 :(得分:1)
你应该为你的内部Grid提供DataContext而不是Control本身,因为外部绑定将在Control中搜索你的ViewAlerts
<Grid x:Name="InnerGrid">
<ItemsControl ItemsSource="{Binding Path=Alerts}"
ItemTemplateSelector="{StaticResource AlertDataTemplateSelector}">
</ItemsControl>
</Grid>
public AlertControl()
{
this.InitializeComponent();
InnerGrid.DataContext = this;
}
之后你可以绑定到警报,警报将被绑定到你的InnerGrid里面的ItemsControl