2011-05-20 102 views
4

我设法创建了一个树视图组合框作为它的itempresenter使用selected item behavior 在这里。组合框 - 树视图,关闭项目选择?

<Popup x:Name="PART_Popup" AllowsTransparency="true" Focusable="false" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom"> 
    <Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}"> 
     <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"> 
     <ScrollViewer> 
      <TreeView x:Name="PART_TreeView" ItemsSource="{TemplateBinding ItemsSource}"> 
       <Interactivity:Interaction.Behaviors> 
       <ComboTreeView:BindableSelectedItemBehaviour SelectedItem="{Binding RelativeSource={RelativeSource AncestorType={x:Type ComboBox} }, Path=SelectedItem, Mode=TwoWay}" />  
       </Interactivity:Interaction.Behaviors>             
       </TreeView>        
     </ScrollViewer> 
     </Border> 
    </Microsoft_Windows_Themes:SystemDropShadowChrome> 
</Popup> 

在treeview中选择一个项目正确设置组合框选定的项目。我不知道如何关闭弹出选择。每次我必须选择并点击控件以外的弹出窗口才能消失。这可以在XAML中完成吗?

回答

0

在行为BindableSelectedItemBehaviour中,我添加了以下逻辑。我想我会将其转变为新的行为,但这是有效的。

private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) 
    { 
     this.SelectedItem = e.NewValue; 

     var treeView = (TreeView)sender; 
     var control = (FrameworkElement)treeView.TemplatedParent; 
     ComboBox combo; 

     do 
     { 
      combo = control as ComboBox; 

      if (combo != null) 
      { 
       break; 
      } 
     } 
     while ((control = (FrameworkElement)control.TemplatedParent) != null); 

     if (combo == null) 
     { 
      return; 
     } 

     Dispatcher.BeginInvoke(new Action(() => combo.IsDropDownOpen = false)); 
    } 
3

我不相信它可以在XAML中完成,但它可以在代码隐藏来实现:

void EnsureComboPopupClosed(ComboBox cb) 
{ 
    if (cb == null || cb.Template == null) 
     return; 
    Popup popup = cb.Template.FindName("PART_Popup", cb) as Popup; 
    if (popup == null) 
     return; 
    popup.IsOpen = false; 
} 

你可以使用一个事件处理程序来调用这个函数。

0

我在xaml ala中完成了一个事件触发器。如果有人对此有任何优化,那么请尽量提出建议,我对此非常青睐。

UPDATE ...这部分工作,除了现在ComboBox将不会再次打开后,你选择和树中的项目。

... xmlns:s="clr-namespace:System;assembly=mscorlib" ... 
... 
<ControlTemplate.Resources> 
    .... 
    <Storyboard x:Key="ClosePopup" 
       Duration="0:0:0" 
       Storyboard.TargetName="PART_Popup" 
       Storyboard.TargetProperty="IsOpen" > 
     <ObjectAnimationUsingKeyFrames> 
      <DiscreteObjectKeyFrame KeyTime="0:0:0"> 
       <DiscreteObjectKeyFrame.Value> 
        <s:Boolean>False</s:Boolean> 
       </DiscreteObjectKeyFrame.Value> 
      </DiscreteObjectKeyFrame> 
     </ObjectAnimationUsingKeyFrames> 
    </Storyboard> 
    ... 
</ControlTemplate.Resources> 
    ... 
    <TreeView x:Name="PART_TreeView" ... > 
     ... 
     <TreeView.Triggers> 
      <EventTrigger RoutedEvent="TreeView.SelectedItemChanged"> 
       <EventTrigger.Actions> 
        ... 
        <BeginStoryboard Storyboard="{StaticResource ClosePopup}"/> 
       </EventTrigger.Actions> 
      </EventTrigger> 
     </TreeView.Triggers> 
     ... 
    </TreeView> 
    ...