Powiązanie ComboBox z enum zagnieżdżonym w klasie
Szaleję z wiązaniem comboboxu z właściwością typową dla enum, gdzie enum jest zadeklarowane w tej samej klasie.
Staram się podążać za odpowiedzią tutaj(wpf combobox wiąże się z enum, co zrobiłem źle?) W szczególności używam sugerowanego kodu MarkupExtension i pasującego kodu xaml.
Mój działający kod to:
Definiowanie Enum w osobnym pliku.
namespace EnumTest
{
public enum TestEnum {one, two, three, four };
}
Klasa używająca Enum (należy zauważyć, że kod propertyChanged został usunięty w celu uproszczenia rzeczy):
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;
}
}
}
Plik programu, który używa klasy:
namespace EnumTest
{
public partial class Window1 : Window
{
Test _oTest = new Test();
public Window1()
{
InitializeComponent();
cmbBox.DataContext = _oTest;
}
}
}
Metoda rozszerzenia do wyświetlania 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);
}
}
}
I kod xaml, który jest używany do wyświetlania danych:
<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>
To wszystko jest dobre i eleganckie, ale chcę zdefiniować Enumw ciągu klasy Test i odrzuć Enum z zakresu globalnego. Tak jak:
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;
}
}
}
Pytanie SO, o którym wspomniałem, odnosi się do pasującej składni xaml jako:
<ComboBox Name="cmbBox"
...
ItemsSource="{Binding Source={w:EnumValues EnumType=w:Test+TestEnum}}"
...
/>
Ale to (rodzaj) nie działa dla mnie. Gdy wykonuję czystą kompilację, na pasku stanu VS 2008 otrzymuję komunikat „Udało się zbudować”, ale w xaml pojawia się również błąd
Type 'Test+TestEnum' was not found.
Ale kod działa zgodnie z oczekiwaniami!
Oznacza to jednak, że projektant xaml nie zostanie załadowany. Więc jestem trochę wkręcony w wykonywanie jakiejkolwiek pracy wpf, dopóki nie mogę usunąć błędu xaml.
Zastanawiam się teraz, czy jest to problem z VS 2008 SP1, a nie problem z mojej strony.
Edytować
Uściśliłem moje stwierdzenie problemu.Wypróbowałem pierwsze rozwiązanie Joela, ale skończyło się na uruchomieniu kodui 2 błędy xamlWypróbowałem drugie rozwiązanie Joela i to działało prosto z pudełka - więc idę z tym!Uwagi Pytanie SO, które otrzymałem od kodu MarkupExtension używa tego stylu składni dla xaml:
<ComboBox ItemsSource="{w:EnumValues w:TestEnum}"/>
Kiedy używam tego, otrzymuję błąd kompilacji mówiąc, że żaden konstruktor EnumValues nie przyjmuje 1 parametru. Zrobiłem kilka googli i wydaje się, że jest to błąd w VS. Używam VS 2008 SP1. Widziałem komentarze, które odnosiły się do tego, że jest to wersja beta VS 2010. W każdym razie dlatego używam składni xaml
<ComboBox ItemsSource="{w:EnumValues EnumType=w:TestEnum}"/>
Jak działa ta składnia!