Я экспериментировал с TemplatedControl в качестве обходного пути, потому что я использую TemplatedControl, и я не хочу иметь дополнительные свойства на ViewModel, чтобы справиться с этим. по отображению, но загрузка/сохранение с помощью ID. В этом тестовом примере Project.Managerid. Это работает, но было бы неплохо не придется жестко кодировать тип в этом шаблонном коде позади, как я сейчас делаю с «LookupiTem». Должно быть возможно обойти это путем настройки x: dataType = "viewModels: lookupitem" < /code> или что-то в этом роде.
Есть идеи?
Код: Выделить всё
< /code>
codebehind: < /p>
public class ChangeTrackingHeaderComboBox : TemplatedControl
{
private object? _selectedItem;
private int? _selectedValue;
public static readonly DirectProperty SelectedItemProperty =
AvaloniaProperty.RegisterDirect(nameof(SelectedItem),
o => o.SelectedItem,
(o, v) => o.SelectedItem = v,
defaultBindingMode: BindingMode.TwoWay,
enableDataValidation: true);
public static readonly DirectProperty SelectedValueProperty =
AvaloniaProperty.RegisterDirect(nameof(SelectedValue),
o => o.SelectedValue,
(o, v) => o.SelectedValue = v,
defaultBindingMode: BindingMode.TwoWay,
enableDataValidation: true);
public static readonly StyledProperty ItemsProperty = AvaloniaProperty
.Register(nameof(Items));
public static readonly StyledProperty SelectedIndexProperty = AvaloniaProperty
.Register(nameof(SelectedIndex));
public static readonly StyledProperty ItemTemplateProperty = AvaloniaProperty
.Register(nameof(ItemTemplate));
public object? SelectedItem
{
get => _selectedItem;
set
{
SetAndRaise(SelectedItemProperty, ref _selectedItem, value);
OnSelectedItemChanged();
}
}
public int? SelectedValue
{
get => _selectedValue;
set
{
SetAndRaise(SelectedValueProperty, ref _selectedValue, value);
OnSelectedValueChanged();
}
}
public IEnumerable Items
{
get => GetValue(ItemsProperty);
set => SetValue(ItemsProperty, value);
}
public int SelectedIndex
{
get => GetValue(SelectedIndexProperty);
set => SetValue(SelectedIndexProperty, value);
}
public IDataTemplate ItemTemplate
{
get => GetValue(ItemTemplateProperty);
set => SetValue(ItemTemplateProperty, value);
}
protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error)
{
base.UpdateDataValidation(property, state, error);
if (property == SelectedItemProperty)
{
DataValidationErrors.SetError(this, error);
}
if (property == SelectedValueProperty)
{
DataValidationErrors.SetError(this, error);
}
}
private void OnSelectedItemChanged()
{
// LookupItem should not be hard coded
if (SelectedItem is LookupItem selectedItem)
{
if (SelectedValue == selectedItem.Id) return;
if (Items is IEnumerable items)
{
var selectedItemDisplayMember = selectedItem.DisplayMember;
SelectedValue = items.SingleOrDefault(x => x.DisplayMember == selectedItemDisplayMember).Id;
}
}
}
private void OnSelectedValueChanged()
{
// LookupItem should not be hard coded
if (Items is IEnumerable items)
{
if (SelectedItem == null)
{
SelectedItem = items.SingleOrDefault(x => x.Id == SelectedValue);
return;
}
if (SelectedItem is LookupItem selectedItem)
{
if (selectedItem.Id == SelectedValue) return;
SelectedItem = items.SingleOrDefault(x => x.Id == SelectedValue);
}
}
}
}
< /code>
app.xaml:
< /code>
mainwindow < /p>
< /code>
viewmodel: < /p>
public sealed class MainViewModel : ViewModelBase
{
private Project _project;
public MainViewModel()
{
Managers = new ObservableCollection();
// Simulating loading Managers from database
for (var i = 1; i < 12; i++)
{
Managers.Add(new LookupItem
{
Id = i,
DisplayMember = $"Manager {i}"
});
}
// One single Project loaded from database
Project = new Project
{
Id = 1,
Name = "Project 1",
ManagerId = Managers.LastOrDefault()?.Id
};
}
public ObservableCollection Managers { get; }
public Project Project
{
get => _project;
private set
{
if (value == _project) return;
_project = value;
OnPropertyChanged();
}
}
}
< /code>
Модели: < /p>
public sealed class Project
{
public int Id { get; set; }
public string Name { get; set; }
public int? ManagerId { get; set; }
}
public sealed class LookupItem
{
public int Id { get; init; }
public string DisplayMember { get; init; }
}
Подробнее здесь: https://stackoverflow.com/questions/751 ... atedcontro