【问题标题】:Windows Universal Implementing Custom SplitView IssuesWindows Universal 实现自定义 SplitView 问题
【发布时间】:2016-07-31 14:24:48
【问题描述】:

我正在尝试使用底部的汉堡按钮实现 SplitView Menue。在由 VisualStudio 提供支持的设计器中,它看起来像这样:

xaml 代码是这样的:

<Page.Resources>
        <ValueConverters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
        <vm:ShellViewModel x:Key="ShellVM"/>
    </Page.Resources>
    <Page.DataContext>
        <Binding Source="{StaticResource ShellVM}"/>
    </Page.DataContext>
    <Grid Background="Transparent">
        <SplitView x:Name="SplitView" IsPaneOpen="True" PaneBackground="Gray" Content="{Binding}" DisplayMode="Inline" VerticalAlignment="Bottom" Margin="0,0,0,40" Width="200" HorizontalAlignment="Left">
            <SplitView.Pane>
                <ListView ItemsSource="{Binding MenueButtons}" Height="Auto">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" Height="Auto">
                                <Grid Width="8" Background="Yellow"  HorizontalAlignment="Left"  Height="20" Margin="-15,4,0,0" Visibility="{Binding Highlighted, Converter={StaticResource BooleanToVisibilityConverter}}"/>
                                <RadioButton FontFamily="Segoe MDL2 Assets"  Style="{StaticResource TextBlockButtonStyle}"  Content="{Binding SymbolIndex}"  Margin="-10,0,14,0"/>
                                <TextBlock Text="{Binding Description}" Margin="-10,5,4,0"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </SplitView.Pane>
        </SplitView>
        <Button x:Name="HamburgerButton" FontFamily="Segoe MDL2 Assets" Content="&#xE700;" HorizontalAlignment="Left" VerticalAlignment="Bottom" Height="40" Foreground="White" FontSize="20"
            Width="50"  Background="Green"/>
    </Grid>

如您所见,我将 ListView 项绑定到 MenueButtons 类型的 ObservableCollection。

现在我正在尝试将 Frame 嵌套在 App.xaml.cs 中的 SplitView 内容中,如下所示:

 protected override void OnLaunched(LaunchActivatedEventArgs e)
        {

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                var shell = Window.Current.Content as Shell;
                rootFrame = null;
                if (shell == null)
                {
                    shell = new Shell();
                    if (rootFrame == null)
                    {
                        rootFrame = new Frame();
                        rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

                        rootFrame.NavigationFailed += OnNavigationFailed;

                        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                        {
                        }
                    }

                    shell.DataContext = rootFrame;

                    Window.Current.Content = shell;
                }
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

Shell.xaml.cs 后面的代码是空的,因为我使用的是 MVVM 模式。但这里是 ShellViewModel 的代码:

   public class ShellViewModel:INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members
    private ObservableCollection<Models.SplitView.MenueButton>  _menueButtons;

    public ObservableCollection<Models.SplitView.MenueButton> MenueButtons
    {
        get { return _menueButtons; }
        set { _menueButtons = value; OnPropertyChanged("MenueButtons"); }
    }
    #endregion INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public ShellViewModel()
    {
        MenueButtons = new ObservableCollection<Models.SplitView.MenueButton>();
        MenueButtons.Add(new Models.SplitView.MenueButton { Description = "Statistic", SymbolIndex = "\uEA40" });
        MenueButtons.Add(new Models.SplitView.MenueButton { Description = "Settings", SymbolIndex = "\uE713" });
        MenueButtons.Add(new Models.SplitView.MenueButton { Description = "Home", SymbolIndex = " \uE80F", Highlighted = true });

    }
}

现在是我遇到的问题:

  • 应用程序启动后应该可以显示主页,但它不起作用
  • 我遇到了在 Designer 中没有发生的绑定错误

绑定错误:

错误:BindingExpression 路径错误:找不到“菜单按钮”属性 在“Windows.UI.Xaml.Controls.Frame”上。绑定表达式: 路径='菜单按钮'DataItem='Windows.UI.Xaml.Controls.Frame';目标 元素是'Windows.UI.Xaml.Controls.ListView'(名称='null');目标 属性是“ItemsSource”(类型“对象”)

而且我认为由于 SplitView 太小,嵌套框架不会使用整个屏幕的宽度和高度。

更多信息: ShellViewModel.cs 包含 ObservableCollection。 启动应用程序后,我只能看到绿色的汉堡菜单按钮。

我该如何解决这个错误?

【问题讨论】:

  • 您需要在 shell 页面后面提供代码。 可行的样本会更容易发现错误。
  • @Jerin 好的,我会在稍后更新帖子

标签: c# xaml binding win-universal-app


【解决方案1】:

您的代码中有两个问题。
1) 拆分视图内容的绑定
2) 定义拆分视图宽度

现在对于第一个主要问题,您使用ShellViewModel 作为绑定的dataContext,但在App.xaml 内部,您将datacontext 初始化为rootFrame 的空帧。解决方法是保持绑定到 ShellViewmodel 并传递帧。

 protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            var shell = Window.Current.Content as Shell;
            if (rootFrame == null)
            {
                rootFrame = null;
                if (shell == null)
                {

                    if (rootFrame == null)
                    {
                        rootFrame = new Frame();
                        rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

                        rootFrame.NavigationFailed += OnNavigationFailed;

                        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                        {
                        }
                    }

                    //shell.NewFrame = rootFrame;
                    shell = new Shell(rootFrame);
                    Window.Current.Content = shell;
                }
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

而后面的shell代码会变成

public Shell(Frame frame)
        {
            this.InitializeComponent();
            SplitViewNew.Content = frame;   //this is SplitviewName      
        }

现在Width="200" 定义了完整的Splitview 宽度框架和覆盖。我猜你打算使用OpenPaneLength="200"
外壳视图

<Page.DataContext>
        <vm:ShellViewModel/>
    </Page.DataContext>
    <Grid Background="Transparent">
        <SplitView x:Name="SplitViewNew" IsPaneOpen="True" PaneBackground="Gray"  DisplayMode="Inline" VerticalAlignment="Bottom" Margin="0,0,0,40"  HorizontalAlignment="Left">
            <SplitView.Pane>
                <Grid>
                    <ListView ItemsSource="{Binding MenueButtons}" Height="Auto">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal" Height="Auto">
                                    <Grid Width="8" Background="Yellow"  HorizontalAlignment="Left"  Height="20" Margin="-15,4,0,0" />
                                    <RadioButton FontFamily="Segoe MDL2 Assets"  Style="{StaticResource TextBlockButtonStyle}"  Content="{Binding SymbolIndex}"  Margin="-10,0,14,0"/>
                                    <TextBlock Text="{Binding Description}" Foreground="White" Margin="-10,5,4,0"/>
                                </StackPanel>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </Grid>
            </SplitView.Pane>          
        </SplitView>
        <Button x:Name="HamburgerButton" FontFamily="Segoe MDL2 Assets" Content="&#xE700;" HorizontalAlignment="Left" VerticalAlignment="Bottom" Height="40" Foreground="White" FontSize="20"
            Width="50"  Background="Green"/>
    </Grid>
</Page>

我正在上传Workable Sample,以便在工作状态下更容易看到它。如果您想完全删除代码,现在可以轻松进行更改。

【讨论】:

  • 谢谢,稍后我会仔细查看示例
  • 太棒了,它运行得很好。我个人认为将小型移动设备上的汉堡包按钮放在左下角非常有用,并且看起来很棒:D ty再次
  • 很高兴知道这有帮助。大多数汉堡菜单没有放在底部,因为您可以选择使用底部应用栏。顶部的汉堡有助于在底部应用栏上放置特定于页面的按钮,以便于访问。
  • 更多信息:我现在在 SplitView.xaml.cs 中进行导航,如下所示: var rootframe = SplitView.Content as Frame; rootframe.Navigate(typeof(ExamplePage));
猜你喜欢
  • 2014-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多