问题
I got a problem. I added a frame in the window xaml to load pages in. I can directly load a page into frame with Source tag of the frame. It works. I need to use the code in C# to refer to the link from listbox menu a poplulate an apropriate link when an listbox item is selected. My problem is that I cannot refer the frame in C# code, it just cannot be seen. I defined the frame with x:Name="ContentFrame". When I refer to in in C#, Intellisense tells that "The name "ContentFrame" does not exist in the current context". What I am doing wrong? I am lost here. Any ideas are highly appreciated. Here is the code:
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;
}
}
`
回答1:
You did it almost right. The only problem is the binding to the selected item. Since the Source property of the frame is of type Uri, and has no dynamic converter, you need an own converter, which does the job:
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();
}
}
You now bind the selected item directly with no xpath and the converter extracts the uri string and builds an Uri object. Here is the fully working xaml (no code behind, except the converter):
<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>
The pages have to be in the pages folder of the same directory of the window of course. In my example, I had two pages with a TextBlock "I am Page1/Page2".
Hope i could help you :)
回答2:
I cant exactly understand why your frame cant be referenced. Did you try another name? I would like you to suggest another smarter way to do this. You can use a Binding for the source. Here is a little example:
<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>
Notice the Source binding on the frame. There is also no more x:Name on the Frame.
In the code behind you have to build a propper ItemSource for the combobox. Therefore i built a simple object, which holds a lable and a source.
public class SourceHolder
{
public string Label { get; set; }
public Uri Source { get; set; }
}
In the constructor of your window you can assign the itemssource to your combobox:
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;
}
The result is, that the combobox has two items (Page1, Page2). If you change the item, the frame updates it's content with the given Source of the selected combobox item.
Jan
来源:https://stackoverflow.com/questions/3529765/wpf-page-to-page-navigation-from-listbox-menu-employing-frame-technique