我正在尝试构建我的第一个基于 MVVM 模式的应用程序。
我仍然没有将视图与按钮单击操作隔离开来,因为我陷入了这个问题
ObservableCollection
。型号
public class Anagrafica
{
public int Cod { get; set; }
public string RSoc { get; set; }
public string Via { get; set; }
public string Cap { get; set; }
public string Cit { get; set; }
public string Pro { get; set; }
public string Naz { get; set; }
public string Piva { get; set; }
public string Cfis { get; set; }
public string NTel { get; set; }
public string NFax { get; set; }
public string Email { get; set; }
public string Ntel { get; set; }
public string Web { get; set; }
public string CPag { get; set; }
public string IBAN { get; set; }
public string Note { get; set; }
}
模型服务
public interface IAnagraficheSVC
{
ObservableCollection<Anagrafica> Anagrafiche { get; }
void CercaAna(int cod);
}
public class AnagraficheSVC:IAnagraficheSVC
{
private ObservableCollection<Anagrafica> _anagrafiche = new ObservableCollection<Anagrafica>();
public ObservableCollection<Anagrafica> Anagrafiche => _anagrafiche;
public void CercaAna(int cod)
{
using (OleDbConnection conn = new OleDbConnection($"PROVIDER=Microsoft.Ace.OLEDB.12.0;Data Source= { Properties.Settings.Default.dbdir }"))
{
if (conn == null)
{
throw new Exception("Connection String is Null.");
}
OleDbCommand query = new OleDbCommand($"SELECT * from Cli WHERE Cod={cod}", conn);
OleDbDataAdapter anaDA = new OleDbDataAdapter(query);
DataTable anaDT = new DataTable();
anaDA.Fill(anaDT);
foreach (DataRow row in anaDT.Rows)
{
Anagrafica a = new Anagrafica();
a.Cod = (int)row["Cod"];
a.RSoc = row["Rsoc"].ToString();
a.Via = row["IVia"].ToString();
a.Cap= row["ICap"].ToString();
a.Cit= row["ICit"].ToString();
a.Pro= row["IPro"].ToString();
a.Naz= row["KInt"].ToString();
a.Piva= row["PIva"].ToString();
a.Cfis= row["CFis"].ToString();
a.Email = row["Emai"].ToString();
a.NTel= row["NTel"].ToString();
a.Web= row["KUrl"].ToString();
a.CPag= row["CPag"].ToString();
a.IBAN= row["NBan"].ToString();
a.Note = row["No01"].ToString();
_anagrafiche.Add(a);
}
}
}
}
视图模型
public class AnagraficaVM
{
private IAnagraficheSVC _anagraficheSVC = null;
public ObservableCollection<Anagrafica> Anagrafiche => _anagraficheSVC.Anagrafiche;
public AnagraficaVM(IAnagraficheSVC anagraficheSVC)
{
_anagraficheSVC=anagraficheSVC;
}
public void cercaAna(int cod)
{
_anagraficheSVC.CercaAna(cod);
}
}
查看.xaml.cs
public partial class MainWindow : Window
{
public MainWindow(AnagraficaVM AnaVM)
{
InitializeComponent();
AnaTab.DataContext = AnaVM;
}
private void Cercabtn_Click(object sender, RoutedEventArgs e)
{
(AnaTab.DataContext as AnagraficaVM).cercaAna(int.Parse(txtCod.Text));
}
}
查看(部分)
<TabItem Header="Anagrafica" Name="AnaTab">
<Border Name="pagborder" Padding="20">
<Grid Name="AnaGrid" DataContext="{Binding Anagrafiche}">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Name="lblCod" Style="{StaticResource cod}" FontSize="16" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center"></Label>
<TextBox Name="txtCod" HorizontalAlignment="Left" VerticalAlignment="Center" Width="50" Margin="130,0,0,0" Height="18" Text="{Binding Cod, UpdateSourceTrigger=Explicit}"/>
</ToggleButton>
<Rectangle Grid.Row="1" Grid.ColumnSpan="4" Fill="Transparent" Height="10"/>
<Label Grid.Row="2" Grid.Column="0" FontSize="14" Background="#576CBC">Dati Anagrafici</Label >
<Label Grid.Row="3" Grid.Column="0">Ragione Sociale</Label>
<Label Grid.Row="3" Grid.Column="1">Indirizzo</Label>
<TextBox Grid.Row="4" Grid.Column="0" Name="RagSoc" Text="{Binding RSoc,UpdateSourceTrigger=Explicit}"/>
<TextBox Grid.Row="4" Grid.Column="1" Name="Indirizzo" Width="210" Text="{Binding Via}"/>
应用程序.xaml.cs
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AnagraficheSVC anagraficheSVC = new AnagraficheSVC();
AnagraficaVM anaVM = new AnagraficaVM(anagraficheSVC);
Views.MainWindow mainWindow = new Views.MainWindow(anaVM);
mainWindow.Show();
}
}
如果我理解正确,ObservableCollection 应该在添加、删除、替换项目时自动通知 UI。
在我的例子中没有发生这样的事情:我绑定到 ViewModel 的 ObservableCollection 的文本框没有填充数据(而调试数据位于 ObservableCollection 内部)。
如果我在
_anagraficheSVC.Anagrafiche.Clear();
之前添加 _anagraficheSVC.CercaAna(cod);
,则我插入正在搜索的索引的文本框 txtCod
会被清除(所以我猜 .Clear()
会收到通知?)。_anagraficheSVC.CercaAna(cod);
来填充 ObservableCollection
:它合法吗?
非常感谢您的宝贵时间!
编辑:
如果我在文本框 (
ListBox
) 的同一个容器中添加测试 AnaGrid
并将 ItemsSource
绑定到 Anagrafiche
,则它正在工作:每次我单击该按钮,我都会看到一个新的 Models.Anagrafica
项目添加到了列表。DataContext
听CollectionChanged
吗?
型号
public class Anagrafica
这不是“MV* Patterns”组的模型。在这些模式中,模型是包含所有业务(域)逻辑的应用程序的层。你的班级
Anagrafica
是一个实体。可能是DTO。此类在 ADO 中称为模型。但ADO是Repository层,它是Application Model实现的一部分。
模型服务
这个服务实际上是MVVM中的一个Model。 考虑到您没有收到关于
_anagrafiche
集合可能发生更改的通知,我建议您更改实施以避免任何随机错误。
public class AnagraficheSVC:IAnagraficheSVC
{
// private ObservableCollection<Anagrafica> _anagrafiche = new ObservableCollection<Anagrafica>();
public ObservableCollection<Anagrafica> Anagrafiche {get;} = new();
查看(部分)
老实说,我不能说我完全理解你想在 GUI 中显示的内容。我假设您想要为
Anagrafiche
集合的每个元素创建一个选项卡,并在选项卡中显示该元素的详细信息。
如果我没猜错的话,应该是这样的:
<TabItem Header="Anagrafica" ItemsSource="{Binding Anagrafiche}">
<TabControl.ContentTemplate>
<DataTemplate>
<Border Name="pagborder" Padding="20">
<Grid Name="AnaGrid">
<Grid.RowDefinitions>
<!-- Continuation of the code -->
</TabControl.ContentTemplate>
<!-- Continuation of the code -->
</TabControl>