Определить выбранный HubSection в Hub с двумя HubSections

У меня есть элемент управления хабом с двумя HubSections. Когда выбранный HubSection изменяется, я хочу изменить содержимое AppBar с помощью кнопок, специфичных для раздела.

Прослушивание события SectionsInViewChanged — это общее решение, рекомендуемое для реализации этого поведения, но это событие не запускается, когда есть только две HubSections.

Есть ли другое событие, которое можно использовать для определения текущего HubSection?

Спасибо.


person Birkan Cilingir    schedule 18.01.2015    source источник
comment
Вы читали комментарии к этому ответу (в частности, комментарий Джерри Никсона)? Бывают случаи, когда на странице видно более одного хаб-раздела, так какой же основной хаб-раздел? (Переведите телефон в ландшафтный режим, чтобы понять, что я имею в виду.) Возможно, вместо этого вы могли бы использовать элемент управления Pivot?   -  person Decade Moon    schedule 19.01.2015
comment
Возможно, протестируйте это решение visuallylocated.com/post/2014/08/26/ не уверен, что это решает проблему с двумя разделами   -  person Depechie    schedule 19.01.2015
comment
@Depechie, хотя проблема, которая возникает, когда есть только два раздела, была затронута в статье, как ни странно, это не решает проблему. Но я мог бы использовать это в сочетании с HorizontalOffset из ScrollViewer, чтобы решить, находится ли он в первом разделе или во втором. Спасибо за ссылку.   -  person Birkan Cilingir    schedule 23.01.2015
comment
@DecadeMoon да, я прочитал этот ответ, но я буду использовать это поведение в особом случае, поэтому не думаю, что это вызовет проблемы.   -  person Birkan Cilingir    schedule 23.01.2015


Ответы (2)


@Depechie указал вам правильное направление. Вы можете использовать SelectionHub control Я создал и добавил к нему событие, которое срабатывает при изменении выбранного индекса

public event EventHandler SelectionChanged;

private static void OnSelectedIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var hub = d as SelectionHub;
    if (hub == null) return;

    // do not try to set the section when the user is swiping
    if (hub._settingIndex) return;

    // No sections?!?
    if (hub.Sections.Count == 0) return;
    hub.OnSelectionChanged();
}

private void OnSelectionChanged()
{
    var section = Sections[SelectedIndex];
    ScrollToSection(section);
    var handler = SelectionChanged;
    if(handler != null)
    {
        handler(this, EventArgs.Empty);
    }
}

Вы можете расширить это, добавив к нему аргументы события изменения выбора. При этом вы можете подписаться на событие в своем коде и изменить кнопки панели приложения на основе индекса.

person Shawn Kendrot    schedule 23.01.2015
comment
Я использовал решение поведения в вашем образце. Событие запускается нормально, но hub.Sections.IndexOf(hub.SectionsInView[0]) всегда возвращает ноль (первый раздел), когда в концентраторе только два раздела. Я что-то упускаю? Я считаю, что могу использовать HorizontalOffsetproperty ScrollViewer, чтобы решить, какой раздел имеет большую часть в представлении, но я не уверен, является ли это решением, подверженным ошибкам. Кстати спасибо за статью. - person Birkan Cilingir; 25.01.2015
comment
В конце ScrollerOnViewChanged метода решения в вашей статье я проверил, соответствует ли scrollViewer.HorizontalOffset > (scrollViewer.ViewportWidth / 2), и решил, какой раздел имеет в виду большую часть. Я хотел бы написать части, которые я использовал из вашего решения, в качестве ответа, если это нормально для вас. - person Birkan Cilingir; 25.01.2015
comment
Событие будет срабатывать много раз и, в конечном итоге, сообщит индекс концентратора с предоставленным кодом. - person Shawn Kendrot; 27.01.2015
comment
К сожалению, это работает по-другому, когда я запускаю его. Если имеется более двух разделов, событие ScrollerOnViewChanged срабатывает несколько раз, как вы предлагаете, и в конце концов индекс является правильным. Если я удалю разделы и оставлю только Раздел 1 и Раздел 2, событие будет запущено несколько раз, но на этот раз индекс всегда равен нулю. Поскольку мы проверяем свойство hub.SectionsInView[0], а видимые разделы не меняются, разве это не нормальное поведение? - person Birkan Cilingir; 29.01.2015

После прочтения Статья Шона, предложенная @Depechie. Я попытался реализовать то же решение в своем приложении, чтобы обновить содержимое AppBar с помощью кнопок, специфичных для раздела.

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

    private void ScrollerOnViewChanged(object sender, ScrollViewerViewChangedEventArgs scrollViewerViewChangedEventArgs)
    {
        _settingIndex = true;
        ScrollViewer scrollViewer = sender as ScrollViewer;
        if (scrollViewer.HorizontalOffset > (scrollViewer.ViewportWidth / 2))
            SelectedIndex = 1;
        else
            SelectedIndex = 0;

        _settingIndex = false;
    }

После этого я добавил свойство в свою модель представления, чтобы сохранить выбранный индекс.

    private int _selectedIndex;

    public int SelectedIndex
    {
        get { return _selectedIndex; }
        set
        {
            SetProperty(ref this._selectedIndex, value);
        }
    }

Я использовал поведение в XAML, чтобы обновить SelectedIndex в моей ViewModel.

<Hub>
    <i:Interaction.Behaviors>
        <behaviors:HubSelectionBehavior SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}" />
    </i:Interaction.Behaviors>

    <HubSection>...</HubSection>
    <HubSection>...</HubSection>
</Hub>

Последнее, что нужно сделать, это установить видимость AppBarButtons с помощью этого свойства. SectionIndexToVisibilityConverter сравнивает SelectedIndex с ConverterParameter и возвращает Visibility.Visible, если они равны.

<CommandBar>
    <AppBarButton Label="Open" Icon="World" Command="{Binding OpenInBrowserCommand}" Visibility="{Binding SelectedIndex, Converter={StaticResource SectionIndexToVisibilityConverter}, ConverterParameter=0}"/>

    <AppBarButton Label="Previous" Icon="Back" Command="{Binding PreviousAnswerCommand}" Visibility="{Binding SelectedIndex, Converter={StaticResource SectionIndexToVisibilityConverter}, ConverterParameter=1}"/>
    <AppBarButton Label="Next" Icon="Forward" Command="{Binding NextAnswerCommand}" Visibility="{Binding SelectedIndex, Converter={StaticResource SectionIndexToVisibilityConverter}, ConverterParameter=1}"/>
</CommandBar>

Спасибо @Depechie за предложение статьи и @Shawn за написание статьи :)

person Birkan Cilingir    schedule 05.02.2015