开发者

How to update Frame source from two listboxes on selected item value?

I hope to find an answer on how to achieve functionality I am trying to have. I have two listboxes. I generate content for them from XML. I also define UriSources in XML. I'd like to find out how to achieve a navigation by clicking any listbox item in any listbox. As a result, I need to be able to update Frame's Source property from two different lisboxes. Perphaps, it should be multibind with some converter. Any ideas are highly appreciated.

XAML: Listboxes and Frame:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compati开发者_开发技巧bility/2006" 
mc:Ignorable="d"
x:Class="TwoListboxes_2.MainWindow"
xmlns:local="clr-namespace:TwoListboxes_2"
Title="MainWindow"
Width="1000" Height="700">
<Window.Resources>
    <local:UriConverter x:Key="UriConverter" /> 
    <XmlDataProvider x:Key="PageData" Source="Data/data.xml" XPath="/Pages" />
    <DataTemplate x:Key="SublevelListboxDataTemplate">
        <Grid>
            <TextBlock Text="{Binding XPath=@name}"/>   
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="MainListBoxDataTemplate">  
            <TextBlock Text="{Binding XPath=@name}"/>   
    </DataTemplate>
</Window.Resources>
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">   
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="215"/>
            <ColumnDefinition Width="1"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid >
            <ListBox x:Name="SublevelListbox" Width="80"
                     DataContext="{Binding SelectedItem, ElementName=Nav_ListBox}"
                     ItemTemplate="{DynamicResource SublevelListboxDataTemplate}" 
                     ItemsSource="{Binding XPath=./*}" 
             />
            <Border HorizontalAlignment="Left">
                <ListBox x:Name="Nav_ListBox" 
                         ItemTemplate="{DynamicResource MainListBoxDataTemplate}" 
                         ItemsSource="{Binding Source={StaticResource PageData}, XPath=page}"
                         SelectedValuePath="@UriSource"
                         SelectedIndex="0"
                />
            </Border>
        </Grid>
        <Frame Grid.Column="2" x:Name="ContentFrame" JournalOwnership="OwnsJournal" NavigationUIVisibility="Visible" 
               Source="{Binding SelectedValue, Converter={StaticResource UriConverter}, ElementName=Nav_ListBox, Mode=TwoWay}"
            />
</Grid> 

XML:

<?xml version="1.0" encoding="utf-8"?><Pages xmlns=""> 
    <page name="Name 1" UriSource="Pages/Name1.xaml"  /> 
    <page name="Name 2" UriSource="Pages/Name2.xaml"  > 
                    <level2 name="ALL1" UriSource="Pages/All1.xaml" /> 
            <level2 name="ALL2" UriSource="Pages/All2.xaml" /> 
                    <level2 name="ALL3" UriSource="Pages/All3.xaml" /> 
            <level2 name="ALL4" UriSource="Pages/All4.xaml" /> 
    </page> 
    <page name="Name 3" UriSource="Pages/Name3.xaml"/> 
    <page name="Name 4" UriSource="Pages/Name4.xaml" IsEnabled="True" /> 

UriConverter to alllow listboxitems to be in selected state when its UriSource is loaded into Frame:

public class MultiBindConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {

        if (values[0] != null)
        {
            if (values[1] != null)
            {
                return new Uri(values[1].ToString(), UriKind.RelativeOrAbsolute);
            }
            return new Uri(values[0].ToString(), UriKind.RelativeOrAbsolute);
        }
        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        //throw new NotImplementedException();

        var uri = (Uri)value;
        var uriString = uri.OriginalString;
        if (value != null)
        {
            if (uri.OriginalString.Contains(";component/"))
            {
                uriString = uriString.Substring(uriString.IndexOf("/") + 1);
            }
        }
        return new object[] { uriString, uriString[0], uriString[1] };
    }
    #endregion IMultiValueConverter Members
} 
Thank you in advance.


If I Understand correctly you are able to bind two list box correctly the only problem is with binding frame with two different source. your Guess is right you can achieve this using Multibinding. i am Assuming the second listbox has no default selection.

The multibinding in xaml will be like this

<Frame Grid.Column="2" x:Name="ContentFrame" JournalOwnership="OwnsJournal" NavigationUIVisibility="Visible">
            <Frame.Source>
                <MultiBinding Converter="{StaticResource conv}">
                    <Binding Path="SelectedItem" ElementName="Nav_ListBox"/>
                    <Binding Path="SelectedItem" ElementName="SublevelListbox"/>
                </MultiBinding>
            </Frame.Source>
        </Frame>

Your Converter will be

public class MultiBindConverter : IMultiValueConverter {
        #region IMultiValueConverter Members

        public object Convert (object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
            if (values[0] != null) {
                if (values[1] != null) {
                    return new Uri (values[1].ToString (), UriKind.RelativeOrAbsolute);
                }
                return new Uri (values[0].ToString (), UriKind.RelativeOrAbsolute);
            }
            return null;
        }

        public object[] ConvertBack (object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) {
            throw new NotImplementedException ();
        }

        #endregion IMultiValueConverter Members
    }


I think that the design is that you need to have master list bound to one list box, details list (sub-list) bound second list. The structure i.e. your data model should be,

Masters - List of details - Selected detail view

and you bind the selected detail view to the frame.


Yes i tried it and this does not work. May be you need to keep a property in your data class through which you can bind your frame source and the selectedValue of your listbox items.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜