我正在尝试构建我的第一个基于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; }
}
ModelService
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);
}
}
}
}
ViewModel
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);
}
}
View.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}"/>
App.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.CercaAna(cod);
之前添加_anagraficheSVC.Anagrafiche.Clear();
,我插入索引的文本框txtCod
被清除(所以我猜.Clear()
得到通知?).
我想我错过了一些东西,因为它应该工作。
既然我已经占用了你的时间,你认为这是MVVM模式的一个很好的实现吗?具体来说,方法调用_anagraficheSVC.CercaAna(cod);
来填充ObservableCollection
:合法吗?
非常感谢您的宝贵时间!
编辑:
如果我在文本框(AnaGrid
)的同一个容器中添加一个测试ListBox
,并将ItemsSource
绑定到Anagrafiche
,它可以工作:每次我点击按钮,我看到一个新的Models.Anagrafica
项目添加到列表中。DataContext
是否监听CollectionChanged
?
更新和解决方案:
我就知道会是很蠢的事。
通过输入{Binding Anagrafiche}
,我将Grid
绑定到ObservableCollection
对象,该对象当然没有属性,只有Anagrafica
项。
通过输入{Binding Anagrafiche[0]}
,我得到了第一个项目与他的属性,一切正常。我甚至不需要任何PropertyChanged
事件来添加或删除列表中的项目。
谢谢大家,特别是HeldHasp,谢谢你们的努力和帮助。
1条答案
按热度按时间lpwwtiir1#
型号
public class Anagrafica
这不是来自“MV* Patterns”组的模型。在这些模式中,模型是包含所有业务(领域)逻辑的应用程序的层。类
Anagrafica
是一个实体。可能是DTO。这些类在ADO中称为模型。但ADO是Repository层,它是应用程序模型实现的一部分。ModelService
该服务实际上是MVVM中的一个模型。考虑到您没有收到
_anagrafiche
集合可能发生更改的通知,我建议您更改实现以避免任何随机错误。视图(部分)
老实说,我不能说我完全理解你想在GUI中显示什么。我假设您希望为
Anagrafiche
集合的每个元素创建一个选项卡,并在选项卡中显示元素的详细信息。如果我没猜错,应该是这样的:
这就是github.com/Tvuce/WPFpj.git
下面是一个工作实现:
.我读文本框只绑定到PropertyChanged事件.
如果只需要显示一个元素(对象),那么最好使用INotifyPropertyChanged.PropertyChanged。但是为了举例,为了学习和提高理解,我将向您展示如何使用ObservableCollection来完成这一点。