Pregunta

tengo un Menu objeto (establecido como DataContext) que contiene muchos Options (Menu.Options), que contiene un Name (Option.Name) Y muchos Options (Option.Options). Las colecciones son todas de tipo ObservableCollection<T>.

El menú se carga desde un archivo XML, por lo que la cantidad de opciones y valores puede variar.

Para ayudar a visualizar, aquí está el XAML relevante:

<ListBox ItemsSource="{Binding Path=Options}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <!-- Title -->
                <TextBlock Text="{Binding Path=Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" />
                <!-- Selection -->
                <toolkit:ListPicker ItemsSource="{Binding Path=Options}" SelectionChanged="ListPicker_SelectionChanged">
                    <toolkit:ListPicker.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path=Name}" />
                        </DataTemplate>
                    </toolkit:ListPicker.ItemTemplate>
                    <toolkit:ListPicker.FullModeItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path=Name}" />
                        </DataTemplate>
                    </toolkit:ListPicker.FullModeItemTemplate>
                </toolkit:ListPicker>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Tengo un método ListPicker_SelectionChanged en el evento SelectionChanged, en el que quiero marcar de alguna manera la selección actual en el modelo de datos. Necesito hacerlo usando solo los parámetros suministrados al método, ya que cada seleccionador de List se genera en tiempo de ejecución. Así que no puedo especificar nombres de control reales (que yo sepa de todos modos).

Puedo ver dos opciones posibles:

1) tener un CurrentSelection en el interior Menu.Option, donde puedo poner una referencia al último elemento seleccionado para ese selector de lista

2) tener un Selected atributo en el Option.Option. Sin embargo, la desventaja aquí es asegurarse de que todos los elementos estén anulados cuando se selecciona uno nuevo.

He intentado navegar por el árbol de objetos de sender, pero cualquier cosa que encuentro, como ItemsHost, es inaccesible (privado/protegido).

¿Hay alguna forma de lograr una solución?

¿Fue útil?

Solución

La opción 1 es la mejor, use la vinculación de dos en el Picker.SelectedItem.

<phone:PhoneApplicationPage 
    x:Class="StackOverflowWP7.SO9369491"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
    xmlns:local="clr-namespace:StackOverflowWP7.SO9369491_"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
    <phone:PhoneApplicationPage.DataContext>
        <local:Menu>
            <local:Menu.Options>
                <local:Option Description="Size">
                    <local:Option.Options>
                        <local:Option local:Description="Large" />
                        <local:Option local:Description="Regular" />
                    </local:Option.Options>
                    <local:Option.CurrentSelection>
                        <local:Option local:Description="Regular" />
                    </local:Option.CurrentSelection>
                </local:Option>
            </local:Menu.Options>
        </local:Menu>
    </phone:PhoneApplicationPage.DataContext>
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <ListBox ItemsSource="{Binding Path=Options}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <!-- Title -->
                            <TextBlock Text="{Binding Path=Description}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" />
                            <!-- Selection -->
                            <toolkit:ListPicker ItemsSource="{Binding Path=Options}"
                                                SelectedItem="{Binding CurrentSelection, Mode=TwoWay}" >
                                <toolkit:ListPicker.ItemTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Path=Description}" />
                                    </DataTemplate>
                                </toolkit:ListPicker.ItemTemplate>
                                <toolkit:ListPicker.FullModeItemTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding Path=Description}" />
                                    </DataTemplate>
                                </toolkit:ListPicker.FullModeItemTemplate>
                            </toolkit:ListPicker>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

Aquí está el código detrás

namespace StackOverflowWP7
{
    using Microsoft.Phone.Controls;

    public partial class SO9369491 : PhoneApplicationPage
    {
        // Constructor
        public SO9369491()
        {
            InitializeComponent();

        }

    }

}

namespace StackOverflowWP7.SO9369491_
{
    using System.Collections.ObjectModel;
    using System.Linq;

    public class Menu : Option
    {
        public Menu()
            : base("Main Menu")
        {
        }
    }

    public class Option
    {
        public Option() {}

        public Option(string Name, params string[] choices)
        {
            this.Description = Name;
            foreach (var choice in choices)
            {
                this._options.Add(new Option(choice));
            }
        }

        public string Description { get; set; }

        private ObservableCollection<Option> _options = new ObservableCollection<Option>();
        public ObservableCollection<Option> Options { get { return _options; } }

        private Option _CurrentSelection;

        public Option CurrentSelection
        {
            get { 
                return _CurrentSelection; 
            }
            set
            {
                if (_options.Contains(value))
                {
                    _CurrentSelection = value;
                }
                else
                {
                    _CurrentSelection = _options.FirstOrDefault((o) => o.Description == value.Description);
                }
            }
        }

    }

}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top