C # WPF Listbox с флажками - отображение выбора - PullRequest
1 голос
/ 14 апреля 2011

Я использую Listbox с флажками для выбора данных в нем. Источником является файл XML, например:

<Hosts>
  <Host Location="a">
    <IP>1.1.1.1</IP>
    <HostName>host1</HostName>
  </Host>
  <Host Location="b">
    <IP>2.2.2.2</IP>
    <HostName>host2</HostName>>
  </Host>
</Hosts>

Список правильно отображается с флажками. Когда я выбираю одну или несколько записей, я не могу получить соответствующие имена хостов. Выбор осуществляется:

    private void CheckBox_Checked(object sender, RoutedEventArgs e)
    {
        var cb = sender as CheckBox;
        var item = cb.DataContext;
// a message box here shows that I have the good content (host1, host2) in item
        ListBoxItem listBoxItem = (ListBoxItem)this.MachinesList.ItemContainerGenerator.ContainerFromItem(item);
        listBoxItem.IsSelected = true;
        MessageBox.Show(listBoxItem.ToString());
    }

Я использую кнопку для отображения содержимого:

private void button1_Click(object sender, RoutedEventArgs e)
{
    foreach (Object selecteditem in MachinesList.SelectedItems)
    {
        MessageBox.Show(selecteditem.ToString());
    }
}

Но окно сообщения печатается: System.XML.XmlElement

Боюсь, что выбор применяется ко всем данным XML, а не к конкретному узлу. то есть:

ListBoxItem listBoxItem = (ListBoxItem)this.MachinesList.ItemContainerGenerator.ContainerFromItem(item);

выбирает не узел, а полный элемент XML.

Список сделан с:

<!-- MACHINES LIST -->
        <!-- Grouping option for machines list -->
        <CollectionViewSource x:Key="cvs" Source="{Binding Source={StaticResource HostsData}}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="@Location" />
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
        <!-- Display option for groups in machines list -->
        <DataTemplate x:Key="categoryTemplate">
            <TextBlock Text="{Binding Path=Name}"  FontWeight="Bold" Background="Gold" Margin="0,5,0,0"/>
        </DataTemplate>
        <!-- Display option for machines in machines list -->
        <DataTemplate x:Key="MachinesTemplate">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/> <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <CheckBox Content="{Binding XPath=HostName}" Checked="CheckBox_Checked"   Grid.Row="0" Grid.Column="0"    Margin="1"/>
            </Grid>
        </DataTemplate>

   <ListBox Name="MachinesList"
             Grid.Row="0"    Grid.Column="0"    Grid.RowSpan="2"    TextBlock.FontSize="9" Margin="2"
             ItemsSource="{Binding Source={StaticResource cvs}}"
             ItemTemplate="{StaticResource MachinesTemplate}"
             SelectionMode="Multiple">
        <ListBox.GroupStyle>
            <GroupStyle HeaderTemplate="{StaticResource categoryTemplate}" />
        </ListBox.GroupStyle>
    </ListBox>

Любая помощь? Я застрял там на несколько часов без понятия ..

Ответы [ 2 ]

0 голосов
/ 14 апреля 2011

Предполагая, что вы хотите выбрать элемент Host, то, что у вас есть сейчас, должно работать правильно, но вы не предоставляете достаточно деталей со своими MessageBoxes, чтобы что-то увидеть.Это очень легко увидеть, просто установив точку останова в своих обработчиках событий, но если вы хотите увидеть больше в MessageBoxes, вы можете быть более точным в отношении того, что показывать.

Используя это вместо этого в обработчике Checked, вам следуетобратите внимание, что выбранный элемент является элементом «Host»:

MessageBox.Show((listBoxItem.Content as XmlElement).Name);

При перечислении выбранных элементов вы можете аналогичным образом проверить, какой элемент находится ниже, до необходимого уровня детализации:

foreach (var selecteditem in MachinesList.SelectedItems.OfType<XmlElement>())
{
    MessageBox.Show(selecteditem.InnerXml);
}

Прежде чем начать использовать это по-настоящему, вам также необходимо изменить способ обработки синхронизации CheckBox и ListBoxItem.Как минимум, вам нужно также иметь обработчик Unchecked на CheckBox, но вы можете сделать его намного проще, избавившись от обработчиков событий и используя вместо этого привязку данных:

<DataTemplate x:Key="MachinesTemplate">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <CheckBox Content="{Binding XPath=HostName}" Margin="1"
                  IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}"/>
    </Grid>
</DataTemplate>
0 голосов
/ 14 апреля 2011

Я предполагаю, что вы получаете XElement, потому что вы в первую очередь добавляете его в список MachinesList. Но почему это может быть проблемой? Вы все еще можете выбрать дочерние элементы из этого фрагмента XML и выбрать свое имя хоста.

...