Вторая Призма перестает работать, как только она содержится в другом элементе управления - PullRequest
0 голосов
/ 30 мая 2019

У меня проблема с Prism 7.1, настольным WPF-приложением, в котором я использую Navigation для загрузки вида в один регион («Основной») и связанный набор инструментов во второй регион («Инструменты»).Короткая версия состоит в том, что я заново сделал макет окна, и Prism теперь говорит мне, что области «Инструменты» больше нет.

Это приложение, в основном

-----------------------------------------------------
| "Explore"   |                                     |              
| "Analyze"   |     ("Main" region.  Shows          |
| "Configure" |     whichever view was selected     |
|-------------|     on the top left)                |
| ("Tools"    |                                     |
|  region)    |                                     |
-----------------------------------------------------     

Пользователь нажимает кнопку навигации (например, «Анализ», «Настроить» и т. Д.), И я использую Prism, чтобы перейти в основной регион к соответствующему виду из соответствующего модуля.Эта часть все еще работает.

У меня также есть RegionBehavior, который заставляет «Инструменты» переходить к отдельному представлению, связанному с основным.(Обнаружил этот подход в курсе PluralSight под названием « Проблемы и решения Prism: загрузка зависимых представлений »).

Это работало нормально, когда у меня был уродливый макет с сеткой с парой ContentControls и соответствующими именами регионов.Но сегодня я попытался заменить это на Telerik RadNavigationView.Основной вид по-прежнему хорошо отображается, но вид «Инструменты» теперь не отображается.

Непосредственная причина ясна: у моего RegionBehavior больше нет области «Инструменты», в которую можно поместить представление связанных инструментов.RegionManager говорит, что его там нет.Несмотря на то, что я по-прежнему четко обозначаю его имя в ContentControl, как и раньше.

Но основная причина неясна.Существует еще ContentControl с именем региона «Инструменты».Так почему же Prism не создает (или не добавляет) этот регион?Могу ли я заставить его?

Это старый XAML, который работал:

<Grid Background="{StaticResource GsBackgroundDark}">

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/> <!-- Navigation/Tools Panel -->
        <ColumnDefinition Width="*"/>    <!-- Page Content Region -->
    </Grid.ColumnDefinitions>

    <!-- Left column has navigation buttons above a Prism region for "tools" -->
    <Grid Grid.Column="0">

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>  <!-- Navigation Buttons -->
            <RowDefinition Height="*"/>     <!-- Tools Region -->
        </Grid.RowDefinitions>

         <!-- Traditional list of category buttons used to navigate ItemTemplate left out (not relevant) -->
        <ItemsControl ItemsSource="{Binding AvailablePages, IsAsync=True}"/>

        <!-- "Tools" pane Content Control, bottom left-->

        <Grid Grid.Row="1">
            <ContentControl prism:RegionManager.RegionName="Tool"/>
        </Grid>
    </Grid>

    <!-- Main Content on the right.   -->

    <ContentControl Grid.Column="1" Grid.Row="1" prism:RegionManager.RegionName="Main"/>

</Grid>

Это новый XAML RadNavigationView, который работает , а не .(Я попытался поместить раздел «Инструменты» в элемент PaneFooter)

<Grid Background="{StaticResource GsBackgroundDark}">


    <tk:RadNavigationView x:Name="GridView"Background="Transparent"
                          ItemsSource="{Binding Items}" SelectedItem="{Binding CurrentItem}">
        <tk:RadNavigationView.Content>
            <ContentControl prism:RegionManager.RegionName="Main"/>
        </tk:RadNavigationView.Content>

        <tk:RadNavigationView.PaneFooter>
           <ContentControl Grid.Column="0" prism:RegionManager.RegionName="Tool" />
        </tk:RadNavigationView.PaneFooter>

    </tk:RadNavigationView>

Остальная часть кода (ниже) не изменилась, но я помещаю его здесь, чтобы вы могли увидеть, что он делает.

«Основные» представления определяют связанные виды инструментов с помощью атрибута.Например, вот «AnalyzeView»:

[PageTool(typeof(AnalyzeViewTools))]  // Associate AnalyzeViewTools with this view
public partial class AnalyzeView
    : UserControl
    , IPageView
    , ISupportDataContext
{
    // blah blah blah....
}
public partial class AnalyzeViewTools : UserControl, ISupportDataContext
{
    // blah blah blah...
}

Это атрибут, о котором идет речь:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=true)]
public class PageToolAttribute : Attribute
{
    public Type Type {  get; }
    public PageToolAttribute(Type toolType) { Type = toolType; }
}

И, наконец, это поведение региона, которое я регистрирую во время запуска приложения и котороевыполняет загрузку связанных видов инструментов.Я отметил строку, которая теперь терпит неудачу с «ЭТО СКАЧИ СЕЙЧАС»

public class ToolRegionBehavior : RegionBehavior
{
    public const string BehaviorKey = "ToolRegionBehavior";
    protected override void OnAttach()
    {
        // Our behavior monitors the region's ActiveView collection.

        if (Region.Name == Regions.Main)
            Region.ActiveViews.CollectionChanged += Views_CollectionChanged;
    }

    // A view has been added or removed.  Make the tools panel reflect this

    private void Views_CollectionChanged(
        object sender, 
        NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            // For each view now showing (there should be only one), try to
            // find a tools view for it.  If we find one, inject it into the
            // tools region.  Views are not required to have associated Tool Panels. 

            Debug.Assert(e.NewItems.Count == 0 || e.NewItems.Count == 1);

            foreach (var view in e.NewItems)
            {
                var toolList = new List<UserControl>();

                // If this view supports a tools panel, it will have an attribute
                // So... if you want to add a tool panel to a view, you need
                // to specify this same attribute, just as, for example,
                // OldAnalyzeViewPanel does.

                foreach (var atr in GetCustomAttributes<PageToolAttribute>(view.GetType()))
                {
                    var tool = Activator.CreateInstance(atr.Type) as UserControl;    

                    // If the tool indicates that it wants to share the view's
                    // data context, then pass it over. (It indicates this
                    // by supporting an interface.)

                    if (tool is ISupportDataContext toolCtx && view is ISupportDataContext viewCtx)
                        toolCtx.DataContext = viewCtx.DataContext;

                    toolList.Add(tool);
                }

                // ***************************************
                // **** THIS FAILS NOW  NO SUCH REGION ***
                // ***************************************

                if (Region.RegionManager.Regions.ContainsRegionWithName("Tool"))
                    toolList.ForEach(x => Region.RegionManager.Regions["Tool"].Add(x));
            }
        }

        else if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            // A view was removed from the main region.  Remove the
            // corresponding tool view we previously injected, if any.  At
            // most there should be one.

            if (!Region.RegionManager.Regions.ContainsRegionWithName("Tool"))
                return;

            var region      = Region.RegionManager.Regions["Tool"];
            region.Views.ToList().ForEach(x => region.Remove(x));
        }
    }


    // Helper to get attribute off of views

    private static IEnumerable<T> GetCustomAttributes<T>(Type type)
    {
        return type.GetCustomAttributes(typeof(T), true).OfType<T>();
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...