ObservableCollection 在 WPF 中不会自动通知 UI

问题描述 投票:0回答:1

我正在尝试构建我的第一个基于 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()
会收到通知?)。
我想我错过了一些东西,因为它应该有效。
既然我已经在花时间了,您认为这是 MVVM 模式的一个很好的实现吗? 特别是方法调用
_anagraficheSVC.CercaAna(cod);
来填充
ObservableCollection
:它合法吗?

非常感谢您的宝贵时间!

编辑:
如果我在文本框 (

ListBox
) 的同一个容器中添加测试
AnaGrid
并将
ItemsSource
绑定到
Anagrafiche
,则它正在工作:每次我单击该按钮,我都会看到一个新的
Models.Anagrafica
项目添加到了列表。
DataContext
CollectionChanged
吗?

c# wpf mvvm binding observablecollection
1个回答
0
投票

型号

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>

© www.soinside.com 2019 - 2024. All rights reserved.