MVVM WPF: пытаюсь использовать параметр @в моей хранимой процедуре (SQL Server)

#c# #sql-server #wpf #mvvm

Вопрос:

Я пишу бизнес-приложение WPF, подключенное к SQL Server, и пытаюсь придерживаться шаблона проектирования MVVM.

Я использую фреймворк стилета, но открыт для ответов с использованием любых других фреймворков или без них, пока я могу заставить его работать.

Стилет автоматически связывает модель представления с представлением.

Чего я пытаюсь достичь: я создал хранимую процедуру, которая выглядит следующим образом:

 SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[getLicense]
    @Foretaksnavn nvarchar(50)
AS 
    SELECT tblLicense.ID, LøyvehaverID, KjøretøyID
    FROM tblLicense
    INNER JOIN tblLicenseHolder ON tblLicense.LøyvehaverID = tblLicenseHolder.Foretaksnummer
    WHERE tblLicense.LøyvehaverID = @Foretaksnavn
 

И я хочу использовать его для заполнения сетки данных (имя: dgLicense ). Я соединяю два столбца с помощью INNER JOIN функции и устанавливаю параметр равным @Foretaksnavn .

Пока что — все хорошо.

А затем я написал метод, который находится в модели представления, соответствующей представлению, содержащему сетку данных. Это выглядит так:

 public void FillDataGridLicenses() 
{
    try 
    {
        using (SqlConnection sqlCon = new(ConnectionString.connectionString))
        using (SqlCommand sqlCmd = new("getLicense", sqlCon))
        using (SqlDataAdapter sqlDaAd = new(sqlCmd))
        using (DataSet ds = new()) 
        {
            sqlCon.Open();

            sqlCmd.CommandType = CommandType.StoredProcedure;
            sqlCmd.Parameters.Add("@Foretaksnavn", SqlDbType.NVarChar).Value = /* MISSING CODE GOES HERE */;

            sqlDaAd.Fill(ds);

            foreach (DataRow dr in ds.Tables[0].Rows) 
            {
                Licenses.Add(new License {
                    ID = Convert.ToInt32(dr[0].ToString()),
                    LøyvehaverID = dr[1].ToString(),
                    KjøretøyID = dr[2].ToString(),
                });
            }
        }
    } 
    catch (Exception ex) 
    {
        MessageBox.Show(ex.Message, "Message", MessageBoxButton.OK, MessageBoxImage.Information);
    }
}
 

The /* MISSING CODE GOES HERE */ part is where I need help.
I have a label in the Window which has the data that would work as parameter-value, but I don’t know how to access it.
The label gets it content like this:

First I put the DataContext of the Canvas like this (this for some reason has to be done even though Stylet couples the View with the ViewModel ):

DataContext="{Binding Path=(viewmodel:LicenseHolderViewModel.Selected)}"

and I’ve bound the contents of the label like this:

Content="{Binding Foretaksnavn}"

«Foretaksnavn» is a property holder bound to an BindableCollection (pretty much the same as an ObservableCollection), and corresponds to the Sql server column of the same name which holds the rows I want to sort the DataGrid by.

How can I access the value of it?

This is the XAML markup for the DataGrid:

 <DataGrid
            x:Name="dgLicense"
            Canvas.Left="315"
            Canvas.Top="501"
            Width="332"
            Height="214"
            AutoGenerateColumns="False"
            BorderBrush="#FF707070"
            CanUserAddRows="False"
            CanUserDeleteRows="False"
            FontSize="14"
            IsReadOnly="True"
            Loaded="{s:Action FillDataGridLicenses}"
            ItemsSource="{Binding LicenseHolders}"
            SelectedItem="{Binding Selected, Mode=TwoWay}"
            SelectionMode="Single" SelectionUnit="FullRow" >
    <DataGrid.Columns>
        <DataGridTextColumn
                    Header="ID"
                    IsReadOnly="True"
                    Visibility="Collapsed" 
                    Binding="{Binding Path=ID, UpdateSourceTrigger=PropertyChanged}"/>
        <DataGridTextColumn
                    Header="Løyve"               
                    IsReadOnly="True"
                    Width="122"
                    HeaderStyle="{StaticResource CenterGridHeaderStyle}"
                    Visibility="Visible" 
                    Binding="{Binding Path=LøyveID, UpdateSourceTrigger=PropertyChanged}"/>
        <DataGridTextColumn
                    Header="Reg.nr"
                    IsReadOnly="True"
                    Visibility="Visible" 
                    Width="92"
                    HeaderStyle="{StaticResource CenterGridHeaderStyle}"
                    Binding="{Binding Path=Registreringsnummer, UpdateSourceTrigger=PropertyChanged}"/>
        <DataGridTextColumn
                    Header="Modell"
                    IsReadOnly="True"
                    HeaderStyle="{StaticResource CenterGridHeaderStyle}"
                    Width="*"
                    Visibility="Visible" 
                    Binding="{Binding Path=Kjøretøymodell, UpdateSourceTrigger=PropertyChanged}"/>
        <DataGridTextColumn
                    Header="Operasjonsdato"
                    IsReadOnly="True"
                    Visibility="Collapsed" 
                    Binding="{Binding Path=Operasjonsdato, UpdateSourceTrigger=PropertyChanged}"/>
    </DataGrid.Columns>
</DataGrid>
 

Licenses является экземпляром BindableCollection (вариант ObservableCollection стилей ), который получает свои данные из класса владельца; License.cs, который выглядит следующим образом:

 using Stylet;

namespace Ridel.Hub 
{
    public class License : PropertyChangedBase 
    {
        private int _id;
        public int ID 
        {
            get { return this._id; }
            set { SetAndNotify(ref this._id, value); }
        }

        private string _løyvehaverID;
        public string LøyvehaverID 
        {
            get { return this._løyvehaverID; }
            set { SetAndNotify(ref this._løyvehaverID, value); }
        }

        private string _kjøretøyID;
        public string KjøretøyID 
        {
            get { return this._kjøretøyID; }
            set { SetAndNotify(ref this._kjøretøyID, value); }
        }
    }
}
 

Очень благодарен, если кто-нибудь может предоставить какие-либо советы или помощь!

Комментарии:

1. Какая именно строка создает исключение? Примечание сбоку: вам не нужно SqlDataAdapter и DataSet , вы можете просто зациклить считыватель using(var reader = sqlCmd.ExecuteReader()) while (reader.Read()) .....

2. Привет @Charlieface, sqlCmd.Parameters.Add("@Foretaksnavn", SqlDbType.NVarChar).Value = LblHeaderText.ToString(); это вызывает исключение. Спасибо за примечание, я обязательно разберусь в этом!

3. Я бы предположил LblHeaderText , что это ноль по какой-либо причине, или, возможно, вы действительно хотите LblHeaderText.Text

4. Я совершил досадную ошибку и обновлю свой вопрос…

5. @Charlieface, теперь я обновил свой вопрос. Оказывается, я сделал глупость и использовал совершенно другой метод для привязки содержимого моей этикетки. Огромное спасибо!