【问题标题】:Xaml WinRT Custom User Control with Bindable Collection具有可绑定集合的 Xaml WinRT 自定义用户控件
【发布时间】:2015-01-11 23:32:09
【问题描述】:

我正在尝试制作一个可以在所有视图中重复使用的自定义用户控件。我的 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 个静态定义的警报,所以我知道应该显示一些值。

【问题讨论】:

  • 我认为我需要在 OnAlertCollectionChanged 中做一些事情,但我不确定具体是什么。

标签: c# xaml user-controls windows-runtime


【解决方案1】:

你应该给你的内部 Grid 一个 DataContext 给 this 而不是给 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-12
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-14
    • 2017-12-22
    相关资源
    最近更新 更多