【问题标题】:Expander inside ListBox not showing content when expanded the first time from bindingListBox 内的扩展器在第一次从绑定中扩展时不显示内容
【发布时间】:2013-05-09 11:13:30
【问题描述】:

我有一个对话框窗口,其中包含一个 ListBox,其 ItemTemplate 包含一个扩展器。 它的IsExpanded 绑定到项目视图模型中的一个属性。 ListBoxItemIsSelected 属性也绑定到项目视图模型对象中的IsExpanded 属性。最后,ListBoxSelectedItem 属性绑定到视图模型中的同名属性。

这里的问题是,在显示对话框之前设置视图模型并将其设置为对话框的DataContext 时,列表框中的项目被选中,扩展箭头显示它在展开状态,但不显示展开器的内容。

如果我设置视图模型之后显示对话框,例如。在对话框的 Loaded 处理程序中,事情按预期工作。这里发生了什么,解决它的最佳方法是什么?

对话框窗口定义为:

<Window x:Class="WpfApplication1.Dialog"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:l="clr-namespace:WpfApplication1"
       Title="Dialog" Height="300" Width="300">
  <Grid>
     <ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
        <ListBox.ItemTemplate>
           <DataTemplate>
              <Expander Header="Expander" x:Name="MyExpander" IsExpanded="{Binding IsExpanded, Mode=TwoWay}">
                 <Rectangle Width="100" Height="20" Fill="Red" />
              </Expander>
           </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemContainerStyle>
           <Style TargetType="ListBoxItem">
              <Setter Property="IsSelected" Value="{Binding IsExpanded, Mode=TwoWay}" />
           </Style>
        </ListBox.ItemContainerStyle>
     </ListBox>
  </Grid>

还有 ViewModel(为简洁起见,不包括实现):

public interface IMyViewModel : INotifyPropertyChanged
{
   object SelectedItem { get; set; }
   ObservableCollection<IMyItemViewModel> Items { get; }
}

public interface IMyItemViewModel : INotifyPropertyChanged
{
   bool IsExpanded { get; set; }
}

然后我有一个带有按钮的简单主窗口,其Click 处理程序定义为:

private void Button_Click(object sender, RoutedEventArgs e)
{
   MyViewModel vm = new MyViewModel();
   MyItemViewModel item = new MyItemViewModel();
   vm.Items.Add(item);
   vm.SelectedItem = item;

   Dialog dialog = new Dialog();
   dialog.DataContext = vm;
   dialog.ShowDialog();
}

当我运行应用程序并单击按钮时,会出现对话框,展开箭头表示它处于展开状态,但不显示其内容。单击展开器会折叠它,再次单击它会展开它,这一次会显示内容。 将相同的代码直接放在主窗口而不是对话框中,但是可以正常工作。

如果我只是做一个 Dispatcher.BeginInvoke(new Action(() =&gt; vm.SelectedItem = item); 而不是直接设置它,事情似乎也可以工作,但这感觉有点不稳定。

可以做些什么来解决这个问题?

【问题讨论】:

  • 我会尝试注册到 ListBox.selectionChange 事件并检查是否也尝试使用 snoop 并在内容未显示时检查您的绑定数据
  • 看来 ababyron 认为这是某种测量错误是正确的,因为在 Snoop 或调试模式下查看时,内容的所有属性实际上都设置正确,只是内容未显示在屏幕上。

标签: wpf c#-4.0 data-binding


【解决方案1】:

如果 IsExpanded 属性已设置为 true,则在加载后不会再次测量扩展器的内容。或者换一种说法,内容是在它还没有实际大小时测量的。

我想最简单的解决方案是在加载对话框后设置SelectedItem

dialog.Loaded += (s, x) => vm.SelectedItem = item;

【讨论】:

  • Hmm.. 这不是 WPF 中的错误吗?
  • 如果我的假设是正确的,那么这是框架没有正确处理的情况。所以是的,你可以称之为错误。
  • 您甚至可以在 MS Connect (connect.microsoft.com) 上记录该错误。 WPF Measure 系统是一段复杂的代码; XAML 能够描述他们在单元测试中没有捕获的条件。你击中了其中一​​个;在我看来,Expander 并不是一个特别强大的控件。
  • 是的,好像是这样。或者可能是 ListBoxItem 的错。不管怎样,我在connect.microsoft.com/VisualStudio/feedback/details/787178/… 提交了一个错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多