选项卡控件中的MVVM列表框未更新

本文关键字:列表 更新 MVVM 控件 选项 | 更新日期: 2023-09-27 18:28:57

我正在处理更新问题。我有选项卡控件,列表框绑定到可观察集合

ListBox HorizontalAlignment="Center" Height="450" VerticalAlignment="Top" Width="250"
     x:Name="LbxMenu" Background="{x:Null}" BorderBrush="{x:Null}" 
     ItemsSource="{Binding TestListsNames}" FontFamily="Segoe UI Semilight" FontSize="18"/>

视图模型:

    private ObservableCollection<string> _testListsName;
    public ObservableCollection<string> TestListsNames
    {
        get { return _testListsName; }
        set{ _testListsName = value; }
   }

在将实体插入数据库后,有一个事件调用我的ViewModel中的TestListInitialize方法,该方法应该刷新集合,它的工作方式正如我在调试器中看到的那样。但列表框并没有刷新,我必须重新启动应用程序才能看到更改。当它在单独的窗口中时效果很好,但当我将ui更改为选项卡控件时,它就不起作用了。

更新功能:

private void TestListNamesInitialize()
    {
        TestListsNames = db.GetTestListNamesFromDatabase();
        if (TestListsNames.Count != 0) CanLoad = true;           
    }

初始窗口:

<Controls:MetroWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="Test.View.InitialWindow"
    xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
    xmlns:tabdata="clr-namespace:Test.View.TabItems"
    Title="Testownik" Height="600" Width="900" ShowTitleBar="True" ResizeMode="NoResize" Icon="../GraphicResources/Icon.ico">

<Controls:MetroWindow.RightWindowCommands>
    <Controls:WindowCommands>
        <Button Content="settings" />
        <Button>
            <StackPanel Orientation="Horizontal">
                <TextBlock Margin="4 0 0 0"
               VerticalAlignment="Center"
               Text="about" />
            </StackPanel>
        </Button>
    </Controls:WindowCommands>
</Controls:MetroWindow.RightWindowCommands>
<Controls:MetroAnimatedTabControl x:Name ="MainTabControl">
    <TabItem Header="Learn" Width="280">
        <tabdata:LearnTabItem/>
    </TabItem>
    <TabItem Header="Database" Width="280">
        <tabdata:DatabaseTabItem/>
    </TabItem>
    <TabItem Header="Statistics" Width="299">
        <tabdata:StatisticsTabItem/>
    </TabItem>
</Controls:MetroAnimatedTabControl>

代码背后:

    public partial class InitialWindow : MetroWindow
{
    InitialWindowViewModel viewModel=new InitialWindowViewModel();
    public InitialWindow()
    {
       InitializeComponent();
       DataContext = viewModel;
    }
}

}

数据库选项卡项:

<UserControl x:Class="Test.View.TabItems.DatabaseTabItem"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
         xmlns:tabData="clr-namespace:Test.View.TabItems"
         Height="500" Width="900" Background="White" BorderBrush="Transparent">
<UserControl.Resources>

</UserControl.Resources>
<Grid>
    <Controls:MetroAnimatedTabControl x:Name ="DatabaseTabControl" Grid.Column="0" TabStripPlacement="Left" >
        <TabItem Header="Choose" Width="250" >
            <tabData:ChooseFromDbTabItem/>
        </TabItem>
        <TabItem Header="Add" Width="250">
            <tabData:AddToDbTabItem/>
        </TabItem>
        <TabItem Header="Remove" Width="250">
            <tabData:DeleteFromDbTabItem/>
        </TabItem>
    </Controls:MetroAnimatedTabControl>
</Grid>

代码背后:

    DatabaseViewModel vm = new DatabaseViewModel();
    public DatabaseTabItem()
    {
        InitializeComponent();
        DataContext = vm;
    }
}

从数据库选项卡项中选择:

<UserControl x:Class="Test.View.TabItems.ChooseFromDbTabItem"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Test.View.TabItems"
         xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
         mc:Ignorable="d" 
         d:DesignHeight="500" d:DesignWidth="650" Background="White" BorderBrush="Transparent">
<Grid>
    <ListBox HorizontalAlignment="Center" Height="450" VerticalAlignment="Top" Width="250"
     x:Name="LbxMenu" Background="{x:Null}" BorderBrush="{x:Null}" 
     ItemsSource="{Binding TestListsNames}" FontFamily="Segoe UI Semilight" FontSize="18"/>
</Grid>

代码背后:

  public partial class ChooseFromDbTabItem : UserControl
{
    public ChooseFromDbTabItem()
    {
        InitializeComponent();
    }
}

选项卡控件中的MVVM列表框未更新

您必须引发PropertyChanged事件,因为您更改了整个集合,而不是单个项目(如果您更改了通过Observable更新的单个项目)。

 private ObservableCollection<string> _testListsName;
    public ObservableCollection<string> TestListsNames
    {
        get { return _testListsName; }
        set
        {
            if (_testListsName != value)
            {
                _testListsName = value;
                NotifyPropertyChanged("TestListsNames");
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }

使用属性setter替换列表时,不会引发PropertyChanged事件。一般来说,尽量使集合属性只读,以降低此类错误的风险。相反,清除列表并重新填充它。这将确保视图收到任何更改的通知。

public class ViewModel
{
    private readonly ObservableCollection<string> _testListsName;
    public ObservableCollection<string> TestListsNames
    {
        get { return _testListsName; }
    }
    private void TestListNamesInitialize()
    {
        _testListsName.Clear();
        foreach(string name in db.GetTestListNamesFromDatabase())
        {
            _testListsName.Add(name);
        }
        if (_testListsNames.Count != 0) CanLoad = true;
    }
}

但是,请注意,这将使用.Add()调用在每个项上引发已更改的事件。请参阅此处:我可以以某种方式暂时禁用WPF数据绑定更改吗?

编辑:从您更新的代码。还可以看出,您没有在ChooseFromDbTabItem上设置DataContext。您需要将DataContext属性绑定到公开集合的视图模型:

<TabItem Header="Choose" Width="250" >
    <tabData:ChooseFromDbTabItem DataContext="{Binding}" />
</TabItem>