【问题标题】:WPF: Page to page navigation from listbox menu employing frame technique?WPF:使用框架技术从列表框菜单进行页面导航?
【发布时间】:2011-04-01 13:56:49
【问题描述】:

我遇到了问题。我在窗口 xaml 中添加了一个框架来加载页面。我可以使用框架的 Source 标签直接将页面加载到框架中。有用。我需要使用 C# 中的代码来引用列表框菜单中的链接,并在选择列表框项目时填充适当的链接。我的问题是我无法在 C# 代码中引用框架,它只是看不到。 我用 x:Name="ContentFrame" 定义了框架。当我在 C# 中引用 in 时,Intellisense 会告诉我“名称“ContentFrame”在当前上下文中不存在”。我做错了什么?我在这里迷路了。任何想法都受到高度赞赏。 代码如下:

XAML:

<Frame x:Name="ContentFrame" JournalOwnership="OwnsJournal" NavigationUIVisibility="Hidden" Grid.Column="2" </Frame>

C#

private void SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
    ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
    string itemName = lbi.Content.ToString();
    if ( Nav_ListBox.SelectedItem.Equals("Page1" ) )
    {
        ContentFrame.Source = new Uri("Pages/Page1.xaml", UriKind.Relative);
        Canvas_Frame.NavigationUIVisibility = NavigationUIVisibility.Hidden;
    }
}

`

【问题讨论】:

    标签: wpf navigation frame


    【解决方案1】:

    你做的几乎是对的。唯一的问题是与所选项目的绑定。由于框架的 Source 属性是 Uri 类型,并且没有动态转换器,因此您需要一个自己的转换器来完成这项工作:

    public class UriConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            XmlElement element = value as XmlElement;
    
            if (element != null)
            {
                string uriSource = element.SelectSingleNode("source").InnerText;
                return new Uri(uriSource, UriKind.Relative);
            }
            else
                return null;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    您现在直接绑定所选项目而不使用 xpath,转换器将提取 uri 字符串并构建一个 Uri 对象。这是完整工作的 xaml(没有后面的代码,除了转换器):

    <Window x:Class="FrameTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:FrameTest"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <DataTemplate x:Key="pageTemplate" >
                <StackPanel Orientation="Horizontal" >
                    <TextBlock Text="{Binding XPath=name}" FontSize="14"
                               VerticalAlignment="Center" Margin="4" />
                </StackPanel>
            </DataTemplate>
    
            <XmlDataProvider x:Key="PagesData" XPath="Pages">
                <x:XData>
                    <Pages xmlns="">
                        <page id="page01">
                            <name>Page 1</name>
                            <source>Pages/Page1.xaml</source>
                        </page>
                        <page id="page02">
                            <name>Page 2</name>
                            <source>Pages/Page2.xaml</source>
                        </page>
                    </Pages>
    
                </x:XData>
            </XmlDataProvider>
    
            <local:UriConverter x:Key="UriConverter" />
        </Window.Resources>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200" />
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
    
            <ListBox x:Name="Nav_ListBox" Grid.Column="0" 
                     VerticalAlignment="Top" 
                     TextBlock.Foreground="Black"
                     ItemTemplate="{DynamicResource pageTemplate}"
                     ItemsSource="{Binding  Source={StaticResource PagesData},
                                   XPath=page}"/>
    
            <Frame NavigationUIVisibility="Hidden"  
                   JournalOwnership="OwnsJournal" Grid.Column="1" 
                   Source="{Binding ElementName=Nav_ListBox, Path=SelectedItem,
                                    Converter={StaticResource UriConverter}}"/>
    
        </Grid>
    </Window>
    

    这些页面当然必须在窗口同一目录的 pages 文件夹中。在我的示例中,我有两个带有 TextBlock “我是 Page1/Page2”的页面。

    希望能帮到你:)

    【讨论】:

    • 太棒了。谢谢您的帮助。我非常感谢。
    • 我有一个与您描述的解决方案相关的问题。在单击日记导航的“后退”/“前进”按钮时,我需要更改与 UriSource 相关的列表框项目的选择状态。我也可以有两个按钮,可以执行向后和向前导航命令。我需要使 ListBox 中的选定项目与 ContentFrame 中的页面保持一致。如果您能提供帮助,请告诉我。提前谢谢你。
    【解决方案2】:

    我不能完全理解为什么你的框架不能被引用。你试过别的名字吗?我希望您提出另一种更聪明的方法来做到这一点。您可以对源使用绑定。这是一个小例子:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="24"/>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    
        <ComboBox x:Name="SourceBox" Grid.Row="0"
                  VerticalAlignment="Top"
                  DisplayMemberPath="Label"
                  TextBlock.Foreground="Black"></ComboBox>
    
        <Frame NavigationUIVisibility="Hidden" 
               JournalOwnership="OwnsJournal" Grid.Row="1"
               Source="{Binding ElementName=SourceBox, Path=SelectedItem.Source}"/>
    </Grid>
    

    注意框架上的 Source 绑定。框架上也不再有 x:Name。

    在后面的代码中,您必须为组合框构建一个propper ItemSource。因此,我构建了一个简单的对象,其中包含一个标签和一个源。

    public class SourceHolder
    {
        public string Label { get; set; }
        public Uri Source { get; set; }
    }
    

    在窗口的构造函数中,您可以将 itemssource 分配给您的组合框:

    public Window1()
    {
        List<SourceHolder> sources = new List<SourceHolder>();
        sources.Add(new SourceHolder()
                    {
                        Label = "Page1",
                        Source = new Uri("Page1.xaml", UriKind.Relative)
                    }
            );
    
        sources.Add(new SourceHolder()
                    {
                        Label = "Page2",
                        Source = new Uri("Page2.xaml", UriKind.Relative)
                    }
            );
    
        InitializeComponent();
    
        this.SourceBox.ItemsSource = sources;
    
    }
    

    结果是,组合框有两个项目(Page1,Page2)。如果您更改项目,框架会使用所选组合框项目的给定 Source 更新其内容。

    一月

    【讨论】:

    • PS:当然同样适用于列表框。当我写这篇文章时,我想到了一个组合框:)
    • 谢谢!看起来 Expression Blend 有某种错误。我重新启动它,然后我能够引用框架。真奇怪。我想知道您能否告诉我如何使用 xml 填充标签和 Uri Source。这个想法是有一个将从 xml 生成的列表框。每个项目都有“名称”和“UriLink”。我需要导航到单击列表框项的页面。我尝试过它,但似乎我错过了一些东西。提前谢谢你。
    • 有很多方法可以用内容填充列表框。如果你喜欢使用 XML,我建议你使用 XPath Binding。一个很好的解释示例,您可以在这里找到:msdn.microsoft.com/en-us/library/… 比您不再需要我的“SourceHolder”对象并且实际上后面的代码为零:)
    • 感谢您的领导。我将 XPath Binding 与 XmlDataProvider 一起使用,效果很好。我仍然无法在 ListboxItem Selected 或 Clicked 上分配 Uri。我想知道您是否可以建议使其工作的方法。我包括以下代码:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    相关资源
    最近更新 更多