扩展程序在ListBox中第一次从绑定展开时不显示内容 [英] Expander inside ListBox not showing content when expanded the first time from binding

查看:117
本文介绍了扩展程序在ListBox中第一次从绑定展开时不显示内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对话窗口,其中包含一个 ListBox ,其ItemTemplate包含扩展器。
它的 IsExpanded 绑定到项目视图模型中的属性。 ListBoxItem IsSelected 属性也绑定到 IsExpanded 属性在项目视图模型对象。最后, ListBox SelectedItem 属性绑定到视图模型中具有相同名称的属性。 p>

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



如果我设置了 后的视图模型,显示对话框,例如。在对话框的加载处理程序中,工作正常。这里发生了什么,修复它的最好方法是什么?



对话窗口定义为:

 < 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 =DialogHeight =300Width =300>
< Grid>
< ListBox ItemsSource ={Binding Items}SelectedItem ={Binding SelectedItem,Mode = TwoWay}>
< ListBox.ItemTemplate>
< DataTemplate>
< Expander Header =Expanderx:Name =MyExpanderIsExpanded ={Binding IsExpanded,Mode = TwoWay}>
< Rectangle Width =100Height =20Fill =Red/>
< / Expander>
< / DataTemplate>
< /ListBox.ItemTemplate>
< ListBox.ItemContainerStyle>
< Style TargetType =ListBoxItem>
< Setter Property =IsSelectedValue ={Binding IsExpanded,Mode = TwoWay}/>
< / Style>
< /ListBox.ItemContainerStyle>
< / ListBox>
< / Grid>



而且 ViewModel (为了简洁起见,不包括实现):

  public interface IMyViewModel:INotifyPropertyChanged 
{
object SelectedItem {get;组; }
ObservableCollection< IMyItemViewModel>物品{get;
}

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

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

  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.DataContext = vm;
dialog.ShowDialog();
}

当我运行应用程序并点击按钮时,对话框显示,展开箭头表示它处于展开状态,但其内容不显示。单击扩展器将折叠它,然后再次单击它展开它,此时显示内容。
将相同的代码直接放在主窗口而不是一个对话框中,但是应该是这样。



如果我只是做一个 Dispatcher.BeginInvoke(new Action(()=> vm.SelectedItem = item); 而不是直接设置它们似乎也可以工作,但这感觉有点动摇。 b
$ b

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

解决方案

听起来像如果 IsExpanded 属性已设置为true,则扩展器在加载后不会再次测量,或者换句话说,当内容仍然没有实际



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

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


I have a dialog window that contains a ListBox whose ItemTemplate contains an expander. Its IsExpanded is bound to a property in the item view model. The ListBoxItem's IsSelected property is also bound to the IsExpanded property in the item view model object. And finally the SelectedItem property of the ListBox is bound to a property with the same name in the view model.

The problem here is that when setting up the view model before showing the dialog and setting it to the DataContext of the dialog, the item in the listbox gets selected as it should, the expander arrow shows that it is in the expanded state, but the content of the expander is not displayed.

If I set up the view model after showing the dialog, eg. in the Loaded handler of the dialog things work as expected. What is going on here, and what would be the best way to fix it?

The dialog window is defined as:

<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>

And the ViewModel (implementation not included for the sake of brevity):

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

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

Then I have a simple main window with a button, and its Click handler is defined as:

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();
}

When I run the application and click the button, the dialog shows up, the expander arrow indicates that it is in the expanded state, but its content is not displayed. Clicking on the expander collapses it, and clicking it again expands it, this time showing the content. Putting the same code directly in the Main Window instead of a dialog however works as it is supposed to.

If I just do a Dispatcher.BeginInvoke(new Action(() => vm.SelectedItem = item); instead of setting it directly things also seem to work, but this feels a bit shaky.

What can be done to fix this problem?

解决方案

Sounds like the content of the expander is not measured again after it is loaded, if the IsExpanded property is already set to true. Or to put it another way, the content is measured when it has still no actual size.

I suppose the easiest solution would be to just set the SelectedItem once the dialog has been loaded:

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

这篇关于扩展程序在ListBox中第一次从绑定展开时不显示内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆