【发布时间】:2015-11-06 00:19:25
【问题描述】:
我有一个简单的 UserControl,带有一个显示 V14、V15 等版本的下拉菜单。
我有另一个 ListBox,它的 ItemSource 绑定到 ViewModel 中的一个属性,该属性取决于 Version DropDown 的 SelectedValue。
ViewModel 看起来像这样:
class MultiSelectEnvironmentContextControlViewModel: ViewModelBase
{
private string selectedVersion;
private DomainFacade domainFacade;
private ObservableCollection<string> environments= new ObservableCollection<string>();
public MultiSelectEnvironmentContextControlViewModel()
{
domainFacade = ((App) Application.Current).DomainFacade;
}
public IEnumerable<string> EnvironmentVersions
{
get
{
return (domainFacade.GetEnvironmentVersions().Select(v => "Version " + v));
}
}
public string SelectedVersion
{
get { return selectedVersion; }
set
{
selectedVersion = value;
RaisePropertyChanged("Environments");
}
}
public ObservableCollection<string> Environments
{
get
{
environments = (ObservableCollection<string>)(domainFacade.GetEnvironments(SelectedVersion));
return environments;
}
}
}
我正在跟踪一个属性中的 SelectedVersion,该属性会在 Environments 上引发 PropertyChanged,以便每当 SeelectedVersion 发生变化时,Environments 都应该更新 UI。
我面临的问题是,我运行应用程序,我看到正在填充的版本,但 ListBox 中没有任何内容。
我在 UserControl 的构造函数中将 UserControl 的 DataContext 设置为 ViewModel。
这是我的 Control.cs 文件的样子:
public partial class MultiSelectEnvironmentContextControl : UserControl
{
private static MultiSelectEnvironmentContextControlViewModel dataContext = new MultiSelectEnvironmentContextControlViewModel();
public MultiSelectEnvironmentContextControl()
{
InitializeComponent();
this.DataContext = dataContext;
dataContext.SelectedVersion = (string)this.ComboBoxVersions.SelectedItem;
}
private void ComboBoxVersions_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
dataContext.SelectedVersion = ((ComboBox) sender).SelectedValue.ToString();
}
}
这是 XAML:
<ComboBox Grid.Column="0" Grid.Row="0" x:Name="ComboBoxVersions" SelectedIndex="0" Margin="10" SelectionChanged="ComboBoxVersions_OnSelectionChanged" ItemsSource="{Binding EnvironmentVersions}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<StackPanel Orientation="Horizontal" Grid.Column="1" Grid.Row="0" Margin="10">
<TextBlock VerticalAlignment="Center" Margin="0,0,10,0">Tests to be run for:</TextBlock>
<ComboBox Name="ComboBoxFileTypeSelector" ItemsSource="{Binding AvailableValidationTypes}" DisplayMemberPath="Key" SelectedValuePath="Value" SelectedIndex="0">
</ComboBox>
</StackPanel>
<ListBox x:Name="ListBoxEnvironments" Grid.Column="0" Grid.Row="1" Height="300" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" Margin="10" SelectionMode="Multiple" ItemsSource="{Binding Environments}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Left" Width="800" >
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox x:Name="CheckBoxEnvironment" Content="{Binding}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Margin="5">
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
【问题讨论】:
-
您能否将您的 XAML 发布为列表框,以便我们查看您如何绑定前端
-
问题可能在于您如何声明数据上下文代码隐藏。使用 MVVM 的目的是不要在 UI 元素 .cs 文件中编写代码。您应该改为在 XAML 中声明数据上下文和绑定。
-
从
Environments属性获取器返回一个新的ObservableCollection<string>是一个非常糟糕的主意。如果多次调用该属性,您将处理该集合的多个不同实例。 -
什么?这仍然会在每次调用时创建一个新实例。
-
您是否尝试过在 Environments 属性 getter 中添加断点,调试它并查看它是否在应该填充列表框时被命中?调试应用程序时在 VS 的输出窗口中写入了什么(菜单->调试->Windows->输出)?