Я схожу с ума от привязки выпадающего списка к типизированному для перечисления свойству класса, где само перечисление объявлено в том же классе.
Я пытаюсь следовать приведенному здесь ответу (wbf combobox привязка к enum, что я сделал не так?) В частности, я использую предложенный код MarkupExtension и соответствующий код xaml.
Мой рабочий код:
Определение Enum в отдельном файле.
namespace EnumTest
{
public enum TestEnum {one, two, three, four };
}
Класс, использующий Enum (обратите внимание, что код propertyChanged был удален для упрощения):
namespace EnumTest
{
public class Test : INotifyPropertyChanged
{
private TestEnum _MyVar;
public TestEnum MyVar {
get { return _MyVar; }
set
{
_MyVar = value;
OnPropertyChanged("MyVar");
}
}
public Test()
{
_MyVar = TestEnum.three;
}
}
}
Программный файл, который использует класс:
namespace EnumTest
{
public partial class Window1 : Window
{
Test _oTest = new Test();
public Window1()
{
InitializeComponent();
cmbBox.DataContext = _oTest;
}
}
}
Метод расширения для отображения Enum
namespace EnumTest
{
[MarkupExtensionReturnType(typeof(object[]))]
public class EnumValuesExtension : MarkupExtension
{
public EnumValuesExtension()
{
}
public EnumValuesExtension(Type enumType)
{
this.EnumType = enumType;
}
[ConstructorArgument("enumType")]
public Type EnumType { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (this.EnumType == null)
throw new ArgumentException("The enum type is not set");
return Enum.GetValues(this.EnumType);
}
}
}
И код xaml, который используется для отображения данных:
<Window x:Class="EnumTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:w="clr-namespace:EnumTest"
Title="Window1" Height="300" Width="300">
<Grid>
<ComboBox Name="cmbBox"
Height="20"
Width="80"
ItemsSource="{Binding Source={w:EnumValues EnumType=w:TestEnum}}"
SelectedItem="{Binding Path=MyVar}"
/>
</Grid>
</Window>
Все вышеперечисленное хорошо и хорошо, но я хочу определить Enum в пределах класса Test и исключить Enum из определения в глобальной области видимости. Вот так:
namespace EnumTest
{
public class Test : INotifyPropertyChanged
{
// Declare Enum **INSIDE** the class
public enum TestEnum {one, two, three, four };
private TestEnum _MyVar;
public TestEnum MyVar {
get { return _MyVar; }
set
{
_MyVar = value;
OnPropertyChanged("MyVar");
}
}
public Test()
{
_MyVar = TestEnum.three;
}
}
}
SO вопрос, который я упоминал, ссылается на соответствующий синтаксис xaml:
<ComboBox Name="cmbBox"
...
ItemsSource="{Binding Source={w:EnumValues EnumType=w:Test+TestEnum}}"
...
/>
Но это (вроде) не работает для меня. Когда я делаю чистую сборку, я получаю сообщение «Сборка выполнена успешно» в строке состояния VS 2008, но я также получаю сообщение об ошибке в xaml
Type 'Test+TestEnum' was not found.
Но код работает как положено!
Однако это означает, что конструктор xaml не будет загружаться. Так что я как-то облажался, выполняя какую-то работу с wpf, пока не смогу устранить ошибку xaml.
Теперь мне интересно, если это проблема VS 2008 SP1, а не проблема с моей стороны.
Редактировать
- Сделал мою формулировку проблемы более явной.
- Пробовал первое решение Джоэла, но в итоге я получил код, запускающий и 2 ошибки xaml
- Попробовал 2-е решение Джоэла, и оно сработало прямо из коробки - так что я пойду с этим!
Примечания
SO вопрос, от которого я получил код MarkupExtension, использует этот стиль синтаксиса для xaml:
<ComboBox ItemsSource="{w:EnumValues w:TestEnum}"/>
Когда я использую это, я получаю ошибку компиляции, говорящую, что никакой конструктор EnumValues не принимает 1 параметр. Я немного погуглил, и это похоже на ошибку в VS. Я использую VS 2008 SP1. Я видел некоторые комментарии, которые ссылались на это в бета-версии VS 2010. В любом случае, именно поэтому я использую синтаксис xaml
<ComboBox ItemsSource="{w:EnumValues EnumType=w:TestEnum}"/>
Как работает этот синтаксис!