2010-05-14 2 views
4

У меня есть поле со списком, в котором я хочу отображать объекты и возвращать значения перечислений. При первом открытии поле со списком отображает элементы как предполагаемые, но после выбора значения оно, кажется, исчезает из списка. Но если combobox активен, я могу использовать клавиатуру для перемещения вверх и вниз между другими значениями, поэтому они находятся в списке, но только невидимы.Значения ComboBox исчезают после выбора, когда объекты, используемые для отображения

Я создал небольшое тестовое приложение, чтобы показать свою проблему. При запуске приложения отображается выпадающий со всеми выборами (два первых являются тип объекта, третья строка):

All choices shown on startup http://i42.tinypic.com/ak7rll.png

После выбора синей линии и, когда выпадающий снова это открыло линия отсутствует:

Blue line selected and is missing in popup http://i41.tinypic.com/24awgth.png

Когда строка с текстом «Зеленый» выбирается эта строка еще показывает:

Green line selected and still shown in popup http://i41.tinypic.com/2en3g2r.png

Если бы я выбрал красную линию, единственное, что было бы в списке, это тест «Зеленый».

Я использую .NET Framework 3.5.

Любые подсказки или советы, почему элементы исчезают?


Вот весь код необходим после запуска пустого проекта в Visual Studio.

MainWindow.xaml.cs:

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 

namespace Test 
{ 
    public partial class MainWindow 
    { 
     public MainWindow() 
     { 
     InitializeComponent(); 
     } 

     private ColorComboBoxValue _activeColor; 
     public ColorComboBoxValue ActiveColor 
     { 
     get { return _activeColor; } 
     set 
     { 
      _activeColor = value; 
      Debug.WriteLine("ActiveColor: " + _activeColor.Color); 
     } 
     } 
    } 

    public class ColorList : List<ColorComboBoxValue> { } 

    public class ColorComboBoxValue 
    { 
     public Color Color { get; set; } 
     public Object Object { get; set; } 
    } 

    public enum Color 
    { 
     Red, 
     Blue, 
     Green 
    } 
} 

MainWindow.xaml:

<Window x:Class="Test.MainWindow" x:Name="window" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:System="clr-namespace:System;assembly=mscorlib" 
     xmlns:local="clr-namespace:Test" 
     Title="ComboBoxTest" Height="100" Width="200"> 

    <Window.Resources> 
     <local:ColorList x:Key="ColorList"> 
      <local:ColorComboBoxValue Color="Red"> 
       <local:ColorComboBoxValue.Object> 
        <Path Data="M0,0 L0,30 60,30 60,0 Z" Fill="Red"/> 
       </local:ColorComboBoxValue.Object> 
      </local:ColorComboBoxValue> 
      <local:ColorComboBoxValue Color="Blue"> 
       <local:ColorComboBoxValue.Object> 
        <Path Data="M0,0 L0,30 60,30 60,0 Z" Fill="Blue"/> 
       </local:ColorComboBoxValue.Object> 
      </local:ColorComboBoxValue> 
      <local:ColorComboBoxValue Color="Green"> 
       <local:ColorComboBoxValue.Object> 
        <System:String>Green</System:String> 
       </local:ColorComboBoxValue.Object> 
      </local:ColorComboBoxValue> 
     </local:ColorList> 
    </Window.Resources> 

    <ComboBox ItemsSource="{Binding Source={StaticResource ColorList}}" 
       SelectedItem="{Binding ActiveColor, ElementName=window}"> 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <ContentPresenter Content="{Binding Path=Object}"/> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 
</Window> 
+0

Есть ли какие-либо события on_select, определенные где угодно по ошибке? – Arnej65

+0

Здесь показан весь используемый код, поэтому не существует никаких событий ... –

ответ

3

Его довольно просто.

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

Что происходит, этот DataTemplate загружается, и он показывает ваши объекты. Вы выбираете один элемент с помощью Path, и он устанавливается в выбранном элементе ContentPresenter вашего Combobox (он должен быть показан). Это отделяет путь от вашего исходного объекта, в результате чего ваши элементы «исчезают». Ваши объекты все еще присутствуют, но вы не можете их видеть, потому что у него больше нет видимого объекта, поскольку путь был удален из вашего исходного списка. В случае строки это работает, потому что строка не является объектом WPF.

Надеюсь, что это немного облегчит ситуацию.

Таким образом, теперь для решения:

Если вы хотите сохранить зеленый цвет как текст, вы можете сделать следующее:

Сделайте свой ColorList от типа Color перечислимого:

public class ColorList : List<Color> { } 

Бросьте некоторые вещи прочь:

public partial class Window1 : Window 
{ 
     public Window1() 
    { 
     this.Resources["ColorList"] = new[] { Color.Red, Color.Blue, Color.Green }; 
     InitializeComponent(); 
    } 

     private Color _activeColor; 
    public Color ActiveColor 
    { 
     get { return _activeColor; } 
     set 
     { 
      _activeColor = value; 
     } 
    } 
} 

public class ColorList : List<Color> { } 


public enum Color 
{ 
    Red, 
    Blue, 
    Green 
} 

и расширить свой DataTemplate установить специфичную фик DataTemplate для красного и синего с использованием объектов триггера в вашем DataTemplate:

<Window x:Class="WpfApplication6.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:WpfApplication6="clr-namespace:WpfApplication6" 
Title="ComboBoxTest" Height="100" Width="200"> 


<ComboBox ItemsSource="{Binding Source={StaticResource ColorList}}" 
      SelectedItem="{Binding ActiveColor, ElementName=ComboBoxTest}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <ContentControl Content="{Binding}" x:Name="content" /> 
      <DataTemplate.Triggers> 
       <DataTrigger Binding="{Binding}" Value="{x:Static WpfApplication6:Color.Red}"> 
        <Setter TargetName="content" Property="ContentTemplate"> 
         <Setter.Value> 
          <DataTemplate> 
           <Path Data="M0,0 L0,30 60,30 60,0 Z" Fill="Red"/> 
          </DataTemplate> 
         </Setter.Value> 
        </Setter> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding}" Value="{x:Static WpfApplication6:Color.Blue}"> 
        <Setter TargetName="content" Property="ContentTemplate"> 
         <Setter.Value> 
          <DataTemplate> 
           <Path Data="M0,0 L0,30 60,30 60,0 Z" Fill="Blue"/> 
          </DataTemplate> 
         </Setter.Value> 
        </Setter> 
       </DataTrigger> 
      </DataTemplate.Triggers> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 
</Window> 

Чистый подход:

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

<ComboBox ItemsSource="{Binding Source={StaticResource ColorList}}" 
      SelectedItem="{Binding ActiveColor, ElementName=ComboBoxTest}"> 
    <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <Path Data="M0,0 L0,30 60,30 60,0 Z" Fill="{Binding Converter={StaticResource ColorConverter}}"/> 
      </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

и хороший конвертер, который нужно добавить к ресурсам:

public class ColorConverter : IValueConverter 
{ 
    #region IValueConverter Members 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     switch ((Color)value) 
     { 
      case Color.Red: 
       return Colors.Red; 
      case Color.Blue: 
       return Colors.Blue; 
      case Color.Green: 
       return Colors.Green; 
      default: 
       throw new ArgumentOutOfRangeException("value"); 
     } 
    } 

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

    #endregion 
} 

Much cleaner;) Надеюсь, это поможет. Если у вас есть какие-либо вопросы, я отвечу на них в комментариях!

+0

Большое спасибо за ваш ответ, решение отлично поработало! Часть со связыванием для получения цвета мне не нужна, потому что все объекты в моем приложении - разные пути одного цвета. Просто сделал небольшое приложение с цветами, чтобы легко продемонстрировать мою проблему. Еще раз спасибо :-) –

+0

Также, поскольку ресурс создан как массив, мне не нужно было создавать новый класс «public class ColorList: List {}« –

+0

Нет проблем! Рад, что смог помочь! – Arcturus

Смежные вопросы