WPF C# MVVM -无法在数据库结果后更新绑定

lvmkulzt  于 2023-10-22  发布在  C#
关注(0)|答案(1)|浏览(153)

我正在尝试使用MVVM模型创建WPF应用程序。
目前我被以下几点卡住了;
在应用程序中,有一个选项可以搜索一个数字(注册号),没有什么花哨的只是一个文本框。
当用户按下“搜索”时,我不想将数据从数据库加载到模型中,并将其显示在用户控件上。
这是我的主窗口视图模型

public class MainWindowViewModal : ViewModelBase
{
    //Fields
    private string _zoekenUitvaartnummer;
    private string _zoekenAchternaam;
    private string _zoekenGeboortedatum;
    private bool _volgendePagina = false;

    private IOverledeneRepository overledeneRepository;

    //Properties
    public string ZoekenUitvaartnummer
    {
        get => _zoekenUitvaartnummer;
        set
        {
            _zoekenUitvaartnummer = value;
            OnPropertyChanged(nameof(ZoekenUitvaartnummer));
        }
    }

    //->Commands
    public ICommand SearchUitvaartnummerCommand { get; }

    public MainWindowViewModal()
    {
        overledeneRepository = new OverledeneRepository();
        SearchUitvaartnummerCommand = new ViewModelCommand(ExecuteSearchUitvaartnummerCommand, CanExecuteSearchUitvaartnummerCommand);
        SearchAchternaamCommand = new ViewModelCommand(ExecuteSearchAchternaamCommand, CanExecuteSearchAchternaamCommand);
        
        
    }

    private bool CanExecuteSearchUitvaartnummerCommand(object obj)
    {
        bool validNummerSearch;
        if(string.IsNullOrWhiteSpace(ZoekenUitvaartnummer))
        {
            validNummerSearch = false;
        }
        else
        {
            validNummerSearch = true;
        }
        return validNummerSearch;
    }

    private void ExecuteSearchUitvaartnummerCommand(object obj)
    {
        var SearchUitvaartleider = overledeneRepository.GetUitvaarleiderByUitvaartId(ZoekenUitvaartnummer);
        OverledeneViewModel.Instance.LoadCurrentUitvaartLeider(ZoekenUitvaartnummer);
    }

}

在overledeneRepository.GetUitvaarleiderByUitvaartId(ZoekenUitvaartnummer)上调用数据库

public class OverledeneRepository : RepositoryBase, IOverledeneRepository
    {
        public OverledeneUitvaartleiderModel GetUitvaarleiderByUitvaartId(string uitvaartId)
        {
            OverledeneUitvaartleiderModel uitvaartLeiderGegevens = null;
            using (var connection = GetConnection())
            using (var command = new SqlCommand())
            {
                connection.Open();
                command.Connection = connection;

                command.CommandText = "SELECT UitvaartId, CONCAT(Initialen,' ',Achternaam) as PersoneelName, PersoneelId, Uitvaartnummer " +
                                        " FROM OverledeneUitvaartleider" +
                                        " INNER JOIN ConfigurationPersoneel ON PersoneelId = Id" +
                                        " WHERE Uitvaartnummer=@uitvaartNummer";

                command.Parameters.Add("@uitvaartNummer", System.Data.SqlDbType.VarChar).Value = uitvaartId;
                using (var reader = command.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        uitvaartLeiderGegevens = new OverledeneUitvaartleiderModel()
                        {
                            UitvaartId = (Guid)reader[0],
                            PersoneelNaam = reader[1].ToString(),
                            PersoneelId = (Guid)reader[2],
                            Uitvaartnummer = reader[3].ToString(),
                        };
                    }
                }
            }
            return uitvaartLeiderGegevens;
        }
    }

返回的值被解析为视图模型

public class OverledeneViewModel : ViewModelBase
{
    //Fields
    private string _uitvaartNummer;
    private string _uitvaartLeider;

    
    private IOverledeneRepository overledeneRepository;
    private OverledeneUitvaartleiderModel _uitvaartLeiderModel;

    //Properties
    public OverledeneUitvaartleiderModel UitvaartLeiderInfo
    {
        get
        {
            return _uitvaartLeiderModel;
        }

        set
        {
            _uitvaartLeiderModel = value;
            OnPropertyChanged(nameof(UitvaartLeiderInfo));
        }
    }
    
    private OverledeneViewModel()
    {
        overledeneRepository = new OverledeneRepository();
        UitvaartLeiderInfo = new OverledeneUitvaartleiderModel();
        SaveCommand = new ViewModelCommand(ExecuteSaveCommand, CanExecuteSaveCommand);
    }

     public static OverledeneViewModel Instance {get;} = new();

    public void LoadCurrentUitvaartLeider(string uitvaartNummer)
    {
        var UitvaarLeiderResult = overledeneRepository.GetUitvaarleiderByUitvaartId(uitvaartNummer);
        if (UitvaarLeiderResult != null)
        {
            UitvaartLeiderInfo.Uitvaartnummer = UitvaarLeiderResult.Uitvaartnummer;
            UitvaartLeiderInfo.PersoneelNaam = UitvaarLeiderResult.PersoneelNaam;

        }
    }
}

有了这个模型

public class OverledeneUitvaartleiderModel
    {
        public Guid UitvaartId { get; set; }
        public Guid PersoneelId { get; set; }
        public string PersoneelNaam { get; set; }
        public string Uitvaartnummer { get; set; }
    }

最后,这是我希望数据可见的xaml

<UserControl x:Class="Test.Views.OverledeneView"
   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:Test.ViewModels"
   mc:Ignorable = "d" 
   d:DesignHeight="696.96" d:DesignWidth="1190.257"
   DataContext="{x:Static local:OverledeneViewModel.Instance}">
    <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
        <Grid x:Name="GridOverledeneView" Background="White" ScrollViewer.CanContentScroll="True">
            <TextBox x:Name="input_UitvaartNrOverledene" Text="{Binding Path=uitvaartLeiderModel.Uitvaartnummer, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TabIndex="1" VerticalContentAlignment="Center" HorizontalAlignment="Left" Margin="204,14,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="301" Height="31" FontSize="16" SelectionBrush="#FFD70000" FontFamily="Arial" BindingGroup="{Binding Text, ElementName=UitvaartLeider}"/>
        </Grid>
    </ScrollViewer>
</UserControl>

这是ViewModelBase

public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

我做错了什么?
谁能帮我解释一下我做错了什么?
任何帮助都将不胜感激。
帕特里克

nwsw7zdq

nwsw7zdq1#

最有可能的是,您在OverledeneViewModel类的示例中有混淆。在MainWindowViewModal.ExecuteSearchUitvaartnummerCommand方法中,创建OverledeneViewModel的第一个示例。并在此示例上运行验证方法。

private void ExecuteSearchUitvaartnummerCommand(object obj)
    {
        var SearchUitvaartleider = overledeneRepository.GetUitvaarleiderByUitvaartId(ZoekenUitvaartnummer);
        var DL = new OverledeneViewModel();
        DL.LoadCurrentUitvaartLeider(ZoekenUitvaartnummer);
    }

OverledeneView View类的XAML中,创建另一个处于初始不可变状态的OverledeneViewModel示例。

<UserControl.DataContext>
        <local:OverledeneViewModel/>
    </UserControl.DataContext>

如果您不需要同时使用OverledeneViewModel的多个示例,请尝试使用Singleton。范例:

public class OverledeneViewModel : ViewModelBase
{
    // Some Code
    
    // Hiding the constructor
    private OverledeneViewModel()
    {
        overledeneRepository = new OverledeneRepository();
        UitvaartLeiderInfo = new OverledeneUitvaartleiderModel();
        SaveCommand = new ViewModelCommand(ExecuteSaveCommand, CanExecuteSaveCommand);
    }

     // The only instance available
     public static OverledeneViewModel Instance {get;} = new();

}
private void ExecuteSearchUitvaartnummerCommand(object obj)
    {
        var SearchUitvaartleider = overledeneRepository.GetUitvaarleiderByUitvaartId(ZoekenUitvaartnummer);
        // var DL = new OverledeneViewModel();
        OverledeneViewModel.Instance.LoadCurrentUitvaartLeider(ZoekenUitvaartnummer);
    }
<UserControl x:Class="Test.Views.OverledeneView"
   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:Test.ViewModels"
   mc:Ignorable = "d" 
   d:DesignHeight="696.96" d:DesignWidth="1190.257"
   DataContext={x:Static local:OverledeneViewModel.Instance}>
    <!--<UserControl.DataContext>
        <local:OverledeneViewModel/>
    </UserControl.DataContext>-->

当我把结果放在消息框中时,它显示为1234,也许绑定在某个地方关闭了?真的迷失在这里
我没有马上注意到第二个错误。
在“OverledeneView”中,您已经设置了绑定:

<TextBox x:Name="input_UitvaartNrOverledene"
             Text="{Binding Path=uitvaartLeiderModel.Uitvaartnummer, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
             -----/>

但是,在类“OverledeneViewModel”中没有属性“uitvaartLeiderModel”。
我认为你需要一个这样的约束力:

<TextBox x:Name="input_UitvaartNrOverledene"
             Text="{Binding UitvaartLeiderInfo.Uitvaartnummer, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
             -----/>

**P.S.**这里也有关于“OverledeneUitvaartleiderModel”类实现的注解。它没有INotifyPropertyChanged的实现,这意味着当它的属性更改时,视图不会自动更新。我认为你最好用只读结构替换这个类。

相关问题