Как получить доступ к компонентам/элементам UserControl в Windows Phone 8

Я разработал UserControl для своего телефона Windows 8, который выглядит следующим образом.

<UserControl x:Class="SpinrWindowsMobile.UserControls.ProgressiveLongListSelector"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
             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"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <phone:LongListSelector Grid.Row="0"  Name="longlistselector">
        </phone:LongListSelector>
        <StackPanel Grid.Row="1">
            <ProgressBar Name="listProress" IsIndeterminate="True"></ProgressBar>
            <TextBlock Name="ProgressText" Text="Loading..."></TextBlock>
        </StackPanel>
    </Grid>
</UserControl>

Как вы можете видеть в приведенном выше xaml, я использовал LongListSelector и StackPanel внутри Grid Control. Я использую этот элемент управления в своем MainPage.xaml, который выглядит следующим образом.

<phone:PhoneApplicationPage
    x:Class="SpinrWindowsMobile.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:UserControls="clr-namespace:SpinrWindowsMobile.UserControls"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">     
            <UserControls:ProgressiveLongListSelector>

            </UserControls:ProgressiveLongListSelector>

     </Grid>    
</phone:PhoneApplicationPage>

До этого все в порядке, но я хочу сделать следующее.

  <UserControls:ProgressiveLongListSelector>
                  <UserControls:ProgressiveLongListSelector.longlistselector 
                 ItemsSource="Binding" ItemTemplate="{staticresource myTemplate}">
                  </UserControls:ProgressiveLongListSelector.longlistselector>
    </UserControls:ProgressiveLongListSelector>

Как я могу получить доступ к селектору длинного списка, который является элементом/компонентом UserControl? Преимущество этого I can directly set the LongListSelector Properties in the xaml(in which i am embedding My usercontrol) itself. Для меня такие вещи сегодня необходимы.

может ли кто-нибудь помочь мне, как это сделать?


person Ashwin N Bhanushali    schedule 18.02.2013    source источник


Ответы (2)


Поскольку вы расширяете и модифицируете LongListSelector, я бы рекомендовал создавать подклассы и повторно создавать шаблоны LongListSelector вместо того, чтобы помещать их в UserControl. Это позволит вам получить доступ ко всем существующим свойствам и методам LongListSelector и использовать ваш новый ProgressiveLongListSelector точно так же, как и LongListSelector.

Для начала вы можете создать новый класс, который является подклассом LongListSelector:

public class ProgressiveLongListSelector : LongListSelector {

    public ProgressiveLongListSelector() {
        DefaultStyleKey = typeof(ProgressiveLongListSelector);
    }
}

Обратите внимание на DefaultStyleKey. Вот откуда возьмется новый шаблон управления.

Теперь вы можете разместить следующий стиль в своих ресурсах App.xaml. Обратите внимание, что TargetType — это ProgressiveLongListSelector. Вот как DefaultStyleKey найдет ваш новый стиль по умолчанию.

    <Style TargetType="phoneApp2:ProgressiveLongListSelector">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="phoneApp2:ProgressiveLongListSelector">
                    <Grid Background="{TemplateBinding Background}" d:DesignWidth="480" d:DesignHeight="800">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="ScrollStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition GeneratedDuration="00:00:00.5" />
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="Scrolling">
                                    <Storyboard>
                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VerticalScrollBar" />
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="NotScrolling" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Grid Margin="{TemplateBinding Padding}">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="auto" />
                            </Grid.ColumnDefinitions>
                            <ViewportControl x:Name="ViewportControl" HorizontalContentAlignment="Stretch" VerticalAlignment="Top" />
                            <ScrollBar x:Name="VerticalScrollBar" Grid.Column="1" Margin="4,0,4,0" Opacity="0" Orientation="Vertical" />
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Этот стиль/шаблон является копией стандартного шаблона LongListSelector (извлеченного из Blend). Отсюда вы можете добавить в шаблон другие элементы пользовательского элемента управления, такие как ProgressBar и TextBlock.

person Gary Johnson    schedule 24.02.2013
comment
Привет, Грей, я постараюсь реализовать твой ответ и сообщу тебе, как все прошло, спасибо, приятель. - person Ashwin N Bhanushali; 25.02.2013
comment
Серый. При использовании ProgressiveLongListSelector в XAML компилятор выдает ошибку: указанное значение не может быть присвоено коллекции. Ожидался следующий тип: UIElement. - person Ashwin N Bhanushali; 25.02.2013
comment
Привет, NeedForSpeed, я только что протестировал его на своем конце без каких-либо проблем. Вы делали модификации? И как вы используете его в XAML? Если бы вы могли опубликовать примеры обоих, я могу взглянуть. - person Gary Johnson; 25.02.2013

Что вы можете сделать, так это раскрыть свойства вашего UserContorl, используя механизм DependencyProperty. Затем вы можете установить их в XAML со страницы, которая использует этот UserControl. Я не уверен, хотите ли вы выставить все биты вашего VisualTree, так как это может измениться в будущем. Но вы можете указать некоторые свойства, которые косвенно влияют на поведение вашего UserControl.

Вот пример того, как это можно сделать:

(этот пример взят из моего кода, но я думаю, вы разберетесь, как его адаптировать)

Сначала вы объявляете DependencyProperty в своем UserControl:

public partial class MyUserControl : UserControl
{
    public bool IsEditingMode
    {
        get { return (bool)GetValue(IsEditingModeProperty); }
        set { SetValue(IsEditingModeProperty, value); }
    }

    public static readonly DependencyProperty IsEditingModeProperty =
        DependencyProperty.Register("IsEditingMode", typeof(bool), typeof(MyUserControl), new PropertyMetadata(false, IsEditingModeChanged));
}

private static void IsEditingModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // this will be called when someone would set the exposed property to some new value
}

Затем вы добавляете MyUserControl на некоторую страницу и устанавливаете это свойство:

<phone:PivotItem Header="{Binding Path=LocalizedResources.MyPivotHeader, Source={StaticResource LocalizedStrings}}" Margin="0">
    <my:MyUserControl x:Name="People" IsEditingMode="True"/>
</phone:PivotItem>

Обратите внимание, как IsEditingMode задается в XAML. Конечно, вы также можете установить его из кода, используя оболочку свойства public bool IsEditingMode вокруг файла IsEditingModeProperty.

person Haspemulator    schedule 18.02.2013
comment
не могли бы вы привести пример того, как это может быть достигнуто? - person wandos; 18.02.2013
comment
Спасибо за ваш ответ, но я хочу предоставить LongListSelector в xaml, чтобы я мог напрямую устанавливать свойства, специфичные для LongListSelector, например свойство itemTemplate, свойство itemSource. Я отредактировал вопрос, чтобы вы могли лучше понять, чего я хочу достичь. - person Ashwin N Bhanushali; 19.02.2013
comment
В отредактированном вопросе вы можете увидеть, как я хочу использовать LonglistSelector (один из компонентов моего элемента управления) в XAML. - person Ashwin N Bhanushali; 19.02.2013