2

ListBoxエキスパンダーを含む ItemTemplateを含むダイアログ ウィンドウがあります。これIsExpandedは、アイテム ビュー モデルのプロパティにバインドされています。のプロパティは、アイテム ビュー モデル オブジェクトのプロパティにListBoxItemIsSelectedバインドされます。IsExpanded最後に、 のSelectedItemプロパティはListBox、ビュー モデル内の同じ名前のプロパティにバインドされます。

ここでの問題は、ダイアログを表示する前にビューモデルを設定し、それを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();
}

アプリケーションを実行してボタンをクリックすると、ダイアログが表示され、展開矢印は展開状態であることを示しますが、その内容は表示されません。エキスパンダーをクリックすると折りたたまれ、もう一度クリックすると展開され、今度はコンテンツが表示されます。ただし、ダイアログの代わりにメインウィンドウに同じコードを直接配置すると、想定どおりに機能します。

直接設定する代わりにa を実行すると、うまくいくDispatcher.BeginInvoke(new Action(() => vm.SelectedItem = item);ように見えますが、これは少し不安定に感じます。

この問題を解決するにはどうすればよいですか?

4

1 に答える 1

2

IsExpandedプロパティがすでにtrueに設定されている場合、エキスパンダーのコンテンツはロード後に再度測定されないようです。別の言い方をすれば、コンテンツはまだ実際のサイズがない状態で測定されます。

最も簡単な解決策はSelectedItem、ダイアログがロードされたら設定することだと思います:

dialog.Loaded += (s, x) => vm.SelectedItem = item;
于 2013-05-13T12:47:02.120 に答える