gpt4 book ai didi

c# - WPF ListBox 绑定(bind)首先有效,但之后无效

转载 作者:太空宇宙 更新时间:2023-11-03 10:24:45 24 4
gpt4 key购买 nike

Base Problem => my ListBox won't update when a different ComboBox value is selected

我正在按照 MVVM 模式(或至少尝试这样做)制作 WPF 应用程序。我有一个服务器列表,我根据当前选择的获取“应用”。服务器列表放在一个列表框中,我希望在我通过下拉菜单更改“应用程序”时,列表框使用新服务器进行更新。

View snippet

“当前:”值将根据所做的选择而改变(以便至少绑定(bind)有效)。我有一个实现 INotifyPropertyChanged 的​​ ServerListViewModel 类。这是它的一个片段

ServerListViewModel(片段)

public ServerListViewModel()
{
_serverListModel = new ServerListModel
{
ServerList = ConfigUtility.GetServers()
};
}

...

public BindingList<string> ServerList
{
get { return _serverListModel.ServerList; }
set
{
if (ReferenceEquals(_serverListModel.ServerList, value)) return;
_serverListModel.ServerList = value;
InvokePropertyChanged("ServerList");
}
}

构造函数正常工作并且 ListBox 更新以反射(reflect) ServerList 属性。 “ConfigUtility.GetServers”使用 JSON 文件中事件“应用程序”的保存值。

在这个类中,我设置了一个这样的静态属性,这样我就可以尝试从另一个 View 模型访问这个类

public static ServerListViewModel Instance { get; } = new ServerListViewModel();

SettingsViewModel.cs

下拉菜单位于设置选项卡上,而服务器列表有自己的选项卡。这些选项卡有自己的 View 模型。

这是这个 View 模型的一个片段:

public ComboBoxItem CurrentApplication
{
get { return _settingsModel.CurrentApplication; }
set {
SetCurrentApplication(value);
}
}

private void SetCurrentApplication(ComboBoxItem value)
{
if (ReferenceEquals(_settingsModel.CurrentApplication, value)) return;
_savedSettings = MySettings.Load();
if (value.Content == null)
{
_settingsModel.CurrentApplication =
new ComboBoxItem { Content = _savedSettings.CurrentApplication };
}
else
{
_settingsModel.CurrentApplication = value;
_savedSettings.CurrentApplication = (string)value.Content;
_savedSettings.Save();
ServerListViewModel.Instance.ServerList = ConfigUtility.GetServers();
}
InvokePropertyChanged("CurrentApplication");
}

我还有一个 MySettings 对象,它将值保存到 JSON 文件中,以便我可以保存事件的“应用程序”黑白 session 。

XAML

<TabControl DockPanel.Dock="Bottom" HorizontalAlignment="Stretch" Height="Auto" TabStripPlacement="Bottom">
<!-- Server List -->
<TabItem Name="ServerListTab" Header="Server List">
<TabItem.DataContext>
<viewModel:ServerListViewModel />
</TabItem.DataContext>
<ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
ItemsSource="{Binding ServerList, UpdateSourceTrigger=PropertyChanged}" IsSynchronizedWithCurrentItem="True"
SelectedItem="{Binding SelectedServer}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="FontSize" Value="14"></Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</TabItem>
<!-- Settings -->
<TabItem Name="SettingsTab" Header="Settings">
<TabItem.DataContext>
<viewModel:SettingsViewModel />
</TabItem.DataContext>
<StackPanel>
<TextBlock FontWeight="Bold">Application</TextBlock>
<WrapPanel>
<TextBlock>Current:</TextBlock>
<TextBlock Text="{Binding CurrentApplication.Content}"></TextBlock>
</WrapPanel>
<TextBlock>Select</TextBlock>
<ComboBox Name="TheComboBox" SelectedItem="{Binding CurrentApplication}">
<ComboBoxItem>NetWebServer</ComboBoxItem>
<ComboBoxItem>NetSearchService</ComboBoxItem>
<ComboBoxItem>NetInterface</ComboBoxItem>
</ComboBox>
<TextBlock FontWeight="Bold">Service</TextBlock>
<WrapPanel>
<TextBlock>Current:</TextBlock>
<TextBlock></TextBlock>
</WrapPanel>
<TextBlock>Select</TextBlock>
<ComboBox></ComboBox>
<CheckBox>
Perfomance mode
</CheckBox>
<CheckBox>
Show live servers
</CheckBox>
<CheckBox>
Show test servers
</CheckBox>
<CheckBox>
Show only parameters with IP's
</CheckBox>
</StackPanel>
</TabItem>
</TabControl>

我还没有将它们分成单独的 View 。问题是他们不是在不同文件中使用自己的 View 模型单独的用户控件吗?但是,我已将不同的选项卡项设置为相应的 View 模型。

结论/问题

我怎样才能通过在 ComboBox 中选择一个新项目来更新服务器列表?通过调试我的代码,似乎一切都在逐行工作,所以一定不能以某种方式通知 ListBox 有变化吗?如果我关闭应用程序并选择了不同的“应用程序”,然后重新打开它,它会正确使用保存的设置用新值填充列表框。但是当应用程序打开时,我无法更改 ListBox。有什么想法吗?

最佳答案

在您的 XAML 中,您创建一个 ServerListViewModel 对象,该对象被设置为 TabItem 的 DataContext。

但是,在 SetCurrentApplication 方法中,您更新了另一个 ServerListViewModel 对象的 ServerList 属性(此静态属性的初始值设定项创建了它)。您在 UI 中看不到任何变化,因为用作 DataContext 的 ServerListViewModel 对象实际上没有被触及。

只需使用静态 ServerListViewModel.Instance 属性中的 ServerListViewModel 对象作为您的 DataContext:

<TabItem
DataContext="{x:Static viewModel:ServerListViewModel.Instance}"
Name="SettingsTab" Header="Settings"
>
...

现在,在 SetCurrentApplication 方法中更新 ServerListViewModel.Instance.ServerList 应该会导致数据绑定(bind)更新。

另一个更简洁的选择是避开静态 Instance 属性并在 View 模型之间使用某种消息传递。 SetCurrentApplication 方法可以发送服务器列表应该更新的消息。 ServerListViewModel 类将处理该消息并执行更新服务器列表的实际工作。 MVVM 库(例如 MVVM Light 和其他库)提供了 Messenger 组件来促进这一点。

关于c# - WPF ListBox 绑定(bind)首先有效,但之后无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32018877/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com