Проблема Заполнение ComboBox внутри ListView в WPF - PullRequest
0 голосов
/ 08 июля 2019

Я надеялся, что кто-нибудь поможет мне разобраться с этой проблемой. Кажется, что в комбинированном списке элемент отображается только как отдельные символы, когда источник привязки имеет только одно значение. Если это два или более, это перечисляет пункты должным образом.

Вот две ссылки с людьми, испытывающими похожие проблемы. Ссылка 1 Ссылка 2

<DataTemplate>
  <ComboBox ItemsSource="{Binding 'Clusters'}" 
   SelectedItem="{Binding Path='TargetCluster', Mode=TwoWay}"
   Width="145"
/>

Вот источник товара

$vCenters = @()
        Foreach ($vCenter in $VDIEnvironments) {
           $vCenter | 
              Add-Member -MemberType NoteProperty -Name TargetCluster -Value (
                 $clusters | ? VCName -like $vCenter.Name
              )[0].Name -Force
           $vCenter | 
              Add-Member -MemberType NoteProperty -Name Clusters -Value $(
                 $clusters | ? VCName -like $vCenter.Name
              ).Name -Force
           $vCenter | 
              Add-Member -MemberType NoteProperty -Name TargetDatastore -Value $(
                 $datastores | ? VCName -like $vCenter.Name | Sort-Object -Descending FreeSpaceMB
              )[0].Name -Force
           $vCenter | 
              Add-Member -MemberType NoteProperty -Name Datastores -Value $(
                 $datastores | ? VCName -like $vCenter.Name
              ).Name -Force 
           $vCenter | 
              Add-Member -MemberType NoteProperty -Name TargetPortgroup -Value (
                 $portgroups | ? VCName -like $vCenter.Name | Sort-Object -Descending NumPorts
              )[0].Name -Force
           $vCenter | 
              Add-Member -MemberType NoteProperty -Name Portgroups -Value $(
                 $portgroups | ? VCName -like $vCenter.Name
              ).Name -Force

           $vCenters += $vCenter
        }

Заполнение данных

            $SelectedVCenters = $VCenters | 
               Where-Object Env -like $WPFboxEnvironment.Text | 
               Where-Object Datastores -ne $Null
            $SelectedVCenters | ForEach-Object {
               $WPFboxSrcVCenter.Items.Add($_.Name)
               $WPFlistTgtVCenters.Items.Add($_)
               $WPFlistTgtVCenters.SelectedItems.Add($_)
            }    

Ответы [ 2 ]

0 голосов
/ 16 июля 2019

Спасибо за разъяснения.Мы с коллегой добавили пустой кластер ко всем vCenters, чтобы устранить проблему.Не лучшее решение, но оно работает и решает две проблемы, которые у нас были.

$clusters = Get-Cluster | Select-Object Name, Uid

$clusters | ForEach-Object {
   $_ | Add-Member -MemberType NoteProperty -Name VCName -Value $_.Uid.split('@')[1].split(':')[0]
}

$uniqueVCs = $clusters | select VCName | sort VCName -Unique

foreach ($VC in $uniqueVCs) {
   $clusterplaceholder = [pscustomobject]@{
      'Name'   = "Select a cluster"
      'Uid'    = " "
      'VCName' = $VC.VCName
   }
   $clusters += $clusterplaceholder
}

$clusters = $clusters | sort VCName, Uid
0 голосов
/ 08 июля 2019

Обычно это происходит, когда вы связываете ItemsControl.ItemsSource с string.ItemsControl внутренне обращается к копии коллекции, связанной с индексом ItemsSource, потому что он должен создать контейнер для каждого элемента данных (ItemContainerGenerator), чтобы представить данные какVisual object.
Так как string реализует индексатор, такой как

public char this[int index] { get; }

, он доступен по индексу, как коллекция или массив.

Теперь, когда привязка string к ItemsControl.ItemsSource, string копируется в коллекцию ItemsControl.Items и передается во внутренний ItemContainerGenerator, который отвечает за создание визуальногоэлементы, которые в конечном итоге отображаются как визуальное представление данных.Это ItemContainerGenerator обрабатывает значение string как коллекцию (поскольку string реализует IEnumerable) и обращается к нему по индексу.Благодаря реализованному индексатору string вернет свои базовые символы, а затем генератор создаст контейнер для каждого.Вот почему string выглядит разделенным.

Убедитесь, что вы всегда привязываете к коллекции string, но никогда не к string напрямую, чтобы избежать такого поведения.

Модель представления, которая предоставляет строковое значение и коллекцию строк для привязки

class ViewModel : INotifyPropertyChanged
{
    private string stringValue;
    public string StringValue
    {
      get => this.stringValue;
      set
      {
        this.stringValue= value;
        OnPropertyChanged();
      }
    }

    private ObservableCollection<string> stringValues;
    public ObservableCollection<string> StringValues
    {
      get => this.stringValues;
      set
      {
        this.stringValues= value;
        OnPropertyChanged();
      }
    }
}

MainWindow.xaml, где DataContext - это класс ViewModel

<!-- This ComboBox will display the single characters of the string value (each item is a character)-->
<ComboBox x:Name="comboBox" ItemsSource="{Binding StringValue}" />

<!-- This ComboBox will display the strings of the StringValues collection (each item is a complete string) -->
<ComboBox x:Name="comboBox" ItemsSource="{Binding StringValues}" />

Отображаемые элементы ComboBox (или ItemsControl в целом) фактически являются контейнерами.Контейнер представляет собой визуальное представление данных и является сложным, как UserControl.Контейнер имеет Border, Background, Padding, Margin и т. Д. Это Visual, который состоит из других Visuals (или элементов управления).Один string не может быть отображен таким образом (со шрифтом, цветом шрифта, фоном и т. Д.).

Поэтому ItemsControl должен создать визуальный контейнер для каждого объекта данных.
Это делается с помощью ItemsControl.ItemsPanel, который фактически использует ItemContainerGenerator для достижения этой цели.Итак, внутренне ComboBox (или ItemsControl.ItemsPanel) получает доступ к связанной коллекции ItemsControl.Items, чтобы создать контейнер следующим образом:

IItemContainerGenerator generator = this.ItemContainerGenerator;    
GeneratorPosition position = generator.GeneratorPositionFromIndex(0);

using (generator.StartAt(position, GeneratorDirection.Forward, true))    
{    
    DependencyObject container = generator.GenerateNext();    
    generator.PrepareItemContainer(container);    
}

Как вы можете видеть, генератор обращается к элементам с помощьюиндекс.Под капотом генератор получает доступ к копии ItemsControl.Items (ItemContainerGenerator.ItemsInternal), чтобы получить данные, которые должны храниться в контейнере.Это как-то (внутри генератора) выглядит так:

object item = ItemsInternal[position];

Так как string реализует индексатор, вы можете получить доступ к string также как к массиву:

var someText = "A String";
char firstCharacter = someText[0]; // References 'A' from "A String"

Так что при поискев приведенном выше коде генератора контейнеров теперь вы можете понять, какое влияние оказывают строки

GeneratorPosition position = generator.GeneratorPositionFromIndex(0);

и

generator.StartAt(position, GeneratorDirection.Forward, true)

на string, где позиция - фактический индекс элемента:извлекает символ за символом для сопоставления их с контейнером.

Это упрощенное объяснение того, как ItemsControl обрабатывает исходную коллекцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...