ฉันชอบวัตถุทั้งหมดที่ฉันผูกพันที่จะกำหนดไว้ในของฉันViewModel
ดังนั้นฉันจึงพยายามหลีกเลี่ยงการใช้<ObjectDataProvider>
ใน xaml เมื่อเป็นไปได้
โซลูชันของฉันไม่ใช้ข้อมูลที่กำหนดไว้ในมุมมองและไม่ต้องใช้โค้ด เฉพาะ DataBinding, ValueConverter ที่ใช้ซ้ำได้ซึ่งเป็นวิธีการรับชุดคำอธิบายสำหรับประเภท Enum ใด ๆ และคุณสมบัติเดียวใน ViewModel ที่จะเชื่อมโยง
เมื่อฉันต้องการที่จะผูกEnum
กับComboBox
ข้อความที่ฉันต้องการที่จะแสดงผลไม่ตรงกับค่าของEnum
ฉันจึงใช้แอตทริบิวต์ที่จะให้มันข้อความที่จริงผมต้องการที่จะเห็นใน[Description()]
ComboBox
ถ้าฉันมีจำนวนวันในสัปดาห์มันจะออกมาเป็นแบบนี้:
public enum DayOfWeek
{
// add an optional blank value for default/no selection
[Description("")]
NOT_SET = 0,
[Description("Sunday")]
SUNDAY,
[Description("Monday")]
MONDAY,
...
}
ก่อนอื่นฉันสร้างชั้นผู้ช่วยด้วยวิธีการสองสามอย่างเพื่อจัดการกับ enums วิธีหนึ่งได้รับรายละเอียดสำหรับค่าเฉพาะวิธีอื่นได้รับค่าทั้งหมดและคำอธิบายสำหรับประเภท
public static class EnumHelper
{
public static string Description(this Enum value)
{
var attributes = value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Any())
return (attributes.First() as DescriptionAttribute).Description;
// If no description is found, the least we can do is replace underscores with spaces
// You can add your own custom default formatting logic here
TextInfo ti = CultureInfo.CurrentCulture.TextInfo;
return ti.ToTitleCase(ti.ToLower(value.ToString().Replace("_", " ")));
}
public static IEnumerable<ValueDescription> GetAllValuesAndDescriptions(Type t)
{
if (!t.IsEnum)
throw new ArgumentException($"{nameof(t)} must be an enum type");
return Enum.GetValues(t).Cast<Enum>().Select((e) => new ValueDescription() { Value = e, Description = e.Description() }).ToList();
}
}
ValueConverter
ต่อไปเราจะสร้าง การสืบทอดจากMarkupExtension
ทำให้ง่ายต่อการใช้ใน XAML ดังนั้นเราไม่จำเป็นต้องประกาศว่าเป็นทรัพยากร
[ValueConversion(typeof(Enum), typeof(IEnumerable<ValueDescription>))]
public class EnumToCollectionConverter : MarkupExtension, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return EnumHelper.GetAllValuesAndDescriptions(value.GetType());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
ของฉันViewModel
ต้องการเพียง 1 คุณสมบัติที่ฉันView
สามารถผูกกับทั้งSelectedValue
และItemsSource
คอมโบได้:
private DayOfWeek dayOfWeek;
public DayOfWeek SelectedDay
{
get { return dayOfWeek; }
set
{
if (dayOfWeek != value)
{
dayOfWeek = value;
OnPropertyChanged(nameof(SelectedDay));
}
}
}
และในที่สุดก็ผูกComboBox
มุมมอง (ใช้ValueConverter
ในการItemsSource
ผูก) ...
<ComboBox ItemsSource="{Binding Path=SelectedDay, Converter={x:EnumToCollectionConverter}, Mode=OneTime}"
SelectedValuePath="Value"
DisplayMemberPath="Description"
SelectedValue="{Binding Path=SelectedDay}" />
ในการใช้งานโซลูชันนี้คุณจะต้องคัดลอกEnumHelper
ชั้นเรียนและชั้นเรียนของฉันEnumToCollectionConverter
เท่านั้น พวกเขาจะทำงานกับenums ใด ๆ นอกจากนี้ผมไม่ได้รวมไว้ที่นี่ แต่ValueDescription
ชั้นเป็นเพียงระดับที่เรียบง่ายด้วย 2 คุณสมบัติของวัตถุประชาชนคนหนึ่งที่เรียกว่าหนึ่งเรียกว่าValue
Description
คุณสามารถสร้างด้วยตัวคุณเองหรือคุณสามารถเปลี่ยนรหัสเพื่อใช้Tuple<object, object>
หรือKeyValuePair<object, object>