#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, теперь я обновил свой вопрос. Оказывается, я сделал глупость и использовал совершенно другой метод для привязки содержимого моей этикетки. Огромное спасибо!