#c# #wpf #xaml #mvvm
#c# #wpf #xaml #mvvm
Вопрос:
Доброго времени суток, я столкнулся с проблемой. У меня есть выпадающий список для ввода данных из базы данных. Я могу брать данные из базы данных, но по какой-то причине данные не хотят отображаться в выпадающем списке. Что мне нужно сделать, чтобы отобразить данные? Заранее благодарю вас.
BoatView.xaml:
<UserControl x:Class="OrderBoatNew.WPF.Controls.BoatCard"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OrderBoatNew.WPF.Controls"
xmlns:vm="clr-namespace:OrderBoatNew.WPF.ViewModels"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="400">
<UserControl.DataContext>
<vm:BoatCardViewModel />
</UserControl.DataContext>
<Grid>
<StackPanel Orientation="Horizontal">
<Grid Margin="15 15 0 0">
<Grid.Resources>
<Style TargetType="ComboBox">
<Setter Property="Margin"
Value="0 20 0 0" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Text="Model:"
Grid.Row="0" />
<ComboBox Grid.Row="0"
Width="150"
ItemsSource="{Binding Models}"
DisplayMemberPath="Name" />
<TextBlock Text="Wood:"
Grid.Row="1" />
<ComboBox Grid.Row="1"
ItemsSource="{Binding Woods}" />
<TextBlock Text="Color:"
Grid.Row="2" />
<ComboBox Grid.Row="2"
ItemsSource="{Binding Colors}" />
</Grid>
</StackPanel>
</Grid>
</UserControl>
Я попытался взять обе таблицы и сразу взять имя из таблицы, но ни один из этих вариантов не работает.
BoatCardViewModel.cs
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using OrderBoatNew.Domain.Models;
using OrderBoatNew.Domain.Services;
using OrderBoatNew.EntityFramework.Services;
using OrderBoatNew.EntityFramework;
namespace OrderBoatNew.WPF.ViewModels
{
public class BoatViewModel : ViewModelBase
{
private readonly IDataService<Model> _modelService;
private readonly IDataService<Wood> _woodService;
private readonly IDataService<Color> _colorService;
private List<Model> _models;
public List<Model> Models
{
get => _models;
set
{
_models = value;
OnPropertyChanged(nameof(Models));
}
}
private List<string> _woods;
public List<string> Woods
{
get => _woods;
set
{
_woods = value;
OnPropertyChanged(nameof(Woods));
}
}
private List<string> _colors;
public List<string> Colors
{
get => _colors;
set
{
_colors = value;
OnPropertyChanged(nameof(Colors));
}
}
public BoatViewModel()
{
var contextFactory = new OrderBoatNewDbContextFactory();
_modelService = new GenericDataService<Model>(contextFactory);
_woodService = new GenericDataService<Wood>(contextFactory);
_colorService = new GenericDataService<Color>(contextFactory);
}
public static BoatViewModel LoadBoatViewModel()
{
BoatViewModel boatViewModel = new BoatViewModel();
boatViewModel.LoadValues();
return boatViewModel;
}
private async void LoadValues()
{
await _modelService.GetAll().ContinueWith(task =>
{
if (task.Exception == null)
Models = task.Result.ToList();
});
await _woodService.GetAll().ContinueWith(task =>
{
if (task.Exception == null)
Woods = task.Result.Select(w => w.Name).ToList();
});
await _colorService.GetAll().ContinueWith(task =>
{
if (task.Exception == null)
Colors = task.Result.Where(c => c.ForAdditionalMoney == false)
.Select(c => c.Name)
.ToList();
});
}
}
}
IDataService.cs
using System.Collections.Generic;
using System.Threading.Tasks;
namespace OrderBoatNew.Domain.Services
{
public interface IDataService<T>
{
Task<IEnumerable<T>> GetAll();
Task<T> Get(int id);
Task<T> Create(T entity);
Task<T> Update(int id, T entity);
Task<bool> Delete(int id);
}
}
GenericDataService.cs
using System.Collections.Generic;
using System.Threading.Tasks;
using OrderBoatNew.Domain.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using OrderBoatNew.Domain.Models;
namespace OrderBoatNew.EntityFramework.Services
{
public class GenericDataService<T> : IDataService<T> where T : DomainObject
{
private readonly OrderBoatNewDbContextFactory _contextFactory;
public GenericDataService(OrderBoatNewDbContextFactory contextFactory) { _contextFactory = contextFactory; }
public async Task<IEnumerable<T>> GetAll()
{
using (OrderBoatNewDbContext context = _contextFactory.CreateDbContext())
{
IEnumerable<T> entities = await context.Set<T>().ToListAsync();
return entities;
}
}
public async Task<T> Get(int id)
{
using (OrderBoatNewDbContext context = _contextFactory.CreateDbContext())
{
T entity = await context.Set<T>().FirstOrDefaultAsync((e) => e.ID == id);
return entity;
}
}
public async Task<T> Create(T entity)
{
using (OrderBoatNewDbContext context = _contextFactory.CreateDbContext())
{
EntityEntry<T> createdResult = await context.Set<T>().AddAsync(entity);
await context.SaveChangesAsync();
return createdResult.Entity;
}
}
public async Task<T> Update(int id, T entity)
{
using (OrderBoatNewDbContext context = _contextFactory.CreateDbContext())
{
entity.ID = id;
context.Set<T>().Update(entity);
await context.SaveChangesAsync();
return entity;
}
}
public async Task<bool> Delete(int id)
{
using (OrderBoatNewDbContext context = _contextFactory.CreateDbContext())
{
T entity = await context.Set<T>().FirstOrDefaultAsync((e) => e.ID == id);
context.Set<T>().Remove(entity);
await context.SaveChangesAsync();
return true;
}
}
}
}
UpdateViewModelCommand.cs
#nullable enable
using System;
using System.Windows.Input;
using OrderBoatNew.Domain.Models;
using OrderBoatNew.EntityFramework.Services;
using OrderBoatNew.WPF.Services;
using OrderBoatNew.WPF.State.Navigators;
using OrderBoatNew.WPF.ViewModels;
namespace OrderBoatNew.WPF.Commands
{
public class UpdateViewModelCommand : ICommand
{
private readonly INavigator _navigator;
public UpdateViewModelCommand(INavigator navigator)
{
_navigator = navigator;
}
public bool CanExecute(object? parameter)
{
return true;
}
public void Execute(object? parameter)
{
if (parameter is ViewType viewType)
{
_navigator.CurrentViewModel = viewType switch
{
ViewType.Boats => BoatViewModel.LoadBoatViewModel(),
ViewType.BoatsAccessory => new BoatAccessoryViewModel(),
_ => throw new ArgumentOutOfRangeException()
};
}
}
public event EventHandler? CanExecuteChanged;
}
}
Комментарии:
1. Попробуйте быть более конкретным в отношении проблемы.
Ответ №1:
Прежде всего, вы назначаете экземпляр a BoatCardViewModel
как DataContext
.
<UserControl.DataContext>
<vm:BoatCardViewModel />
</UserControl.DataContext>
Вы никогда не должны этого делать, это нарушает наследование контекста данных. Вы должны либо привязать свойство контекста данных, в котором фактически используется пользовательский элемент управления, если это необходимо, например:
<BoatCard DataContext="{Binding ...}" />
Теперь проблема в том, что модель представления контекста данных создается с использованием конструктора без параметров, который инициализирует службы, но никогда не вызывает их для получения данных.
Другая проблема заключается в том, что LoadBoatViewModel
метод либо вообще не вызывается, либо он бесполезен, поскольку вызов возвращает новый экземпляр a BoatCardViewModel
, который никогда не устанавливается в вашем пользовательском элементе управления. Таким образом, вы потенциально используете два разных экземпляра модели представления, не замечая этого.