UWP MasterDetail控制UserControl依赖属性

时间:2018-02-12 10:05:04

标签: c# xaml uwp user-controls

我正在处理由Windows Template Studio创建的主详细信息页面。我正在尝试在userControl中有一个comboBox,它定义了DetailsTemplate,它从页面中的列表加载它的值。

以下是代码:

ArticlesPage.xaml

<Page
x:Class="Estimates.Views.ArticlesPage"
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"
Style="{StaticResource PageStyle}"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:model="using:Estimates.Models"
xmlns:views="using:Estimates.Views"
xmlns:fcu ="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"
xmlns:cu ="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,5)"
mc:Ignorable="d">
<Page.Transitions>
    <TransitionCollection>
        <NavigationThemeTransition />
    </TransitionCollection>
</Page.Transitions>
<Page.Resources>
    <DataTemplate x:Key="ItemTemplate" x:DataType="model:Article">
        <Grid Height="64" Padding="0,8">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <StackPanel Grid.Column="1" Margin="12,0,0,0" VerticalAlignment="Center">
                <TextBlock Text="{x:Bind Description, Mode=TwoWay}" Style="{ThemeResource ListTitleStyle}"/>
            </StackPanel>
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="DetailsTemplate" x:DataType="views:ArticlesPage">
        <views:ArticlesDetailControl MasterMenuItem="{Binding}" MeasureUnits="{x:Bind MeasureUnits}" />
    </DataTemplate>

    <DataTemplate x:Key="NoSelectionContentTemplate">
        <TextBlock x:Uid="Articles_NoSelection" Style="{StaticResource ListNoSelectionTextStyle}" />
    </DataTemplate>
</Page.Resources>

<Grid>

    <Grid.RowDefinitions>
        <RowDefinition x:Name="TitleRow" Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <TextBlock
        x:Uid="Articles_Title"
        x:Name="TitlePage"
        Margin="12,0,12,7"
        Style="{StaticResource PageTitleStyle}" />

    <controls:MasterDetailsView
        Grid.Row="1"
        x:Name="MasterDetailsViewControl"
        ItemsSource="{x:Bind Items}"
        SelectedItem="{x:Bind Selected, Mode=TwoWay}"
        ItemTemplate="{StaticResource ItemTemplate}"
        NoSelectionContentTemplate="{StaticResource NoSelectionContentTemplate}"
        BorderBrush="Transparent"
        DetailsTemplate="{StaticResource DetailsTemplate}" >
    </controls:MasterDetailsView>

    <Grid VerticalAlignment="Bottom" HorizontalAlignment="Right" Padding="0,15,0,0" Grid.Row="2">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Button x:Uid="AddButton" Grid.Column="0" Margin="5" Click="AddButton"/>
        <Button x:Uid="SaveButton" Grid.Column="1" Margin="5" Click="SaveButton"/>
        <Button x:Uid="DeleteButton" Grid.Column="2" Margin="5" Click="DeleteButton"/>
    </Grid>
    <!--  Adaptive triggers  -->
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="WindowStates">
            <VisualState x:Name="WideState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="640"/>
                </VisualState.StateTriggers>
            </VisualState>
            <VisualState x:Name="NarrowState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="TitlePage.Margin" cu:Value="60,0,12,7" fcu:Value="12,0,12,7"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Grid>

ArticlesPage.xaml.cs

    public sealed partial class ArticlesPage : Page, INotifyPropertyChanged
{
    private Article _selected;
    private ObservableCollection<MeasureUnit> _measureUnits;
    private IRepositoryService _repositoryService { get; set; }

    public Article Selected
    {
        get { return _selected; }
        set { Set(ref _selected, value); }
    }

    public ObservableCollection<MeasureUnit> MeasureUnits
    {
        get { return _measureUnits; }
        set { Set(ref _measureUnits, value);}
    }

    public ObservableCollection<Article> Items { get; private set; } = new ObservableCollection<Article>();

    public ArticlesPage()
    {
        InitializeComponent();
        Loaded += ArticlesPage_Loaded;
        _repositoryService = new RepositoryService();
    }

    private void ArticlesPage_Loaded(object sender, RoutedEventArgs e)
    {
        Items.Clear();

ArticledDetailControl.xaml

<UserControl
x:Class="Estimates.Views.ArticlesDetailControl"
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:model="using:Estimates.Models"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<ScrollViewer Name="ForegroundElement" VerticalScrollMode="Enabled" HorizontalAlignment="Stretch" Padding="12,0">
    <StackPanel HorizontalAlignment="Stretch">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Margin="0,8,0,0">
            <TextBlock
                Margin="12,0,0,0"
                Text="{x:Bind MasterMenuItem.Description, Mode=TwoWay}"
                Style="{StaticResource SubheaderTextBlockStyle}" />
        </StackPanel>
        <StackPanel Name="block" Padding="0,15,0,0">
            <TextBox x:Uid="Description" Text="{x:Bind MasterMenuItem.Description, Mode=TwoWay}" />
            <TextBox x:Uid="Notes" Text="{x:Bind MasterMenuItem.Notes, Mode=TwoWay}" Margin="0,6,0,0"/>
            <Grid Margin="0,6,0,0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="0.33*" />
                    <ColumnDefinition Width="0.33*" />
                    <ColumnDefinition Width="0.33*" />
                </Grid.ColumnDefinitions>
                <ComboBox x:Uid="MeasureUnits" x:Name="MeasureUnitsCB" ItemsSource="{x:Bind MeasureUnits}" Grid.Column="0">
                    <ComboBox.ItemTemplate>
                        <DataTemplate x:DataType="model:MeasureUnit">
                            <TextBlock Text="{x:Bind Description}"/>
                        </DataTemplate>
                    </ComboBox.ItemTemplate>
                </ComboBox>
                <TextBox x:Uid="Price" Text="{x:Bind MasterMenuItem.Price, Mode=TwoWay}" Grid.Column="2" />
            </Grid>
        </StackPanel>
    </StackPanel>
</ScrollViewer>

ArticlesDetailControl.xaml.cs

    public sealed partial class ArticlesDetailControl : UserControl
{
    public Article MasterMenuItem
    {
        get { return GetValue(MasterMenuItemProperty) as Article; }
        set { SetValue(MasterMenuItemProperty, value); }
    }

    public IEnumerable<MeasureUnit> MeasureUnits
    {
        get { return GetValue(MeasureUnitsProperty) as IEnumerable<MeasureUnit>; }
        set { SetValue(MeasureUnitsProperty, value); }
    }

    public static readonly DependencyProperty MasterMenuItemProperty =
        DependencyProperty.Register("MasterMenuItem", typeof(Article), typeof(ArticlesDetailControl), new PropertyMetadata(null, OnMasterMenuItemPropertyChanged));
    public static readonly DependencyProperty MeasureUnitsProperty =
        DependencyProperty.Register("MeasureUnits", typeof(IEnumerable<MeasureUnit>), typeof(ArticlesDetailControl), new PropertyMetadata(null, OnMeasureUnitsPropertyChanged));

    public ArticlesDetailControl()
    {
        InitializeComponent();
    }

    private static void OnMasterMenuItemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = d as ArticlesDetailControl;
        control.ForegroundElement.ChangeView(0, 0, 1);
    }

    private static void OnMeasureUnitsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Debug.WriteLine("PD");
    }
}

所以,问题是:MasterMenuItem是如何填充的?为什么我的属性MeasureUnit它没有在UserControl中填充?

编辑:正如TheZapper在接受的答案中所建议的那样,这里是OnMenuMasterItemPropertyChanged的实现:

        private static void OnMasterMenuItemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = d as ArticlesDetailControl;
        control.ForegroundElement.ChangeView(0, 0, 1);

        if (control.MasterMenuItem.MeasureUnit != null)
        {
            control.MeasureUnitsCB.SelectedItem =
                control.MeasureUnits.First(s => s.Id == control.MasterMenuItem.MeasureUnit.Id);
        }

        if (control.MasterMenuItem.VatCode != null)
        {
            control.VatCodesCB.SelectedItem =
                control.VatCodes.First(s => s.Id == control.MasterMenuItem.VatCode.Id);
        }
    }

我在UserControl的构造函数中加载列表。

1 个答案:

答案 0 :(得分:1)

我猜您的问题是由于在UserControl中绑定到MasterMenuItemProperty

也许你可以在你的用户控件中添加DependencyProperties作为Notes,Description并像这样定义你的模板

<DataTemplate x:Key="DetailsTemplate" x:DataType="views:ArticlesPage">
    <views:ArticlesDetailControl Notes="{x:Bind Notes}" MeasureUnits="{x:Bind MeasureUnits}" />
</DataTemplate>

或者您可以尝试更新Changed-Event中的绑定。

private static void OnMasterMenuItemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = d as ArticlesDetailControl;
    control.ForegroundElement.ChangeView(0, 0, 1);
    *** Update Binding ***
}