0

リストボックスにレンダリングされるユーザーコントロールにあるWPFエキスパンダーに問題があります。基本的に、リストボックス内の各ListItemでPopUpButtonの動作を取得しようとしています。エキスパンダーを開くと、コンテンツは透明であるかのように、またはzオーダーで低くなるように、他のすべての背後にレンダリングされます。WPFポップアップとトグルボタンでもこれを試しましたが(Karle Shivlletのブログ–ポップアップコンテンツを使用したエキスパンダーコントロールで説明されている手法を使用)、役に立ちませんでした。

まず、私がやろうとしていることについて説明しましょう。アプリケーション用に構成する必要のある入力のリストを表示する2つのコントロールがあります。簡単にするために、1つのユーザーコントロールを使用してグラフへの入力を構成し、別のコントロールを使用して単純なExcelグリッドへの入力を制御します。グラフとグリッドの入力にはそれぞれ、構成する必要のあるプロパティがあります。グラフまたはグリッド用に構成する入力のリストを含むListBoxをレンダリングするInputSelectControlと呼ばれる単純なユーザーコントロールを開発しました。ListBoxの各ListItemは、入力の名前(Pressure、ECGなど)のTextBlockと、クリックするとその入力のプロパティエディターを表示するWPFExpanderで構成されます。プロパティエディタの表示は、グラフ入力とグリッド入力のどちらを扱っているかによって異なるため、ControlTemplate型のInputSelectControlでDependencyPropertyを使用しました。これにより、グリッドとグラフがそれぞれ、入力プロパティの編集に必要なプレゼンテーションを提供できるようになります。また、この動作を必要とするグラフとグリッド以上のものがあることに注意してください。したがって、これをプレゼンテーション動作を動的に受信できるユーザーコントロールにしたいという要望があります。

エキスパンダーをプロパティエディターテンプレート内に配置しようとしました。また、さまざまな場所でZIndexを試してみましたが、常に同じ動作になり、エキスパンダーポップアップがリストのListItemsの後ろに表示されます。

以下は、私のアプローチをさらに説明するコードです。うまくいけば、誰かがこの漬物から私を助けることができます。

InputSelectControlを保持するグリッド(グラフなど)コントロールを表すXAML:

<UserControl x:Class="MyApp.GridView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:props="clr-namespace:PopupButtonDependencyProp" mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <!-- Specify the control tempalte we want loaded into the 
             properies popup for a grid-->
        <ControlTemplate x:Key="GridPropertyEditorTemplate" TargetType="ContentControl">
            <props:GridInputPropertyEditor />
        </ControlTemplate>
    </UserControl.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBlock Text="Hello Grid" Margin="5" />

        <!-- Tell the InputSelectControl what template to load into Property 
             Window for each Grid Input item -->
        <props:InputSelectControl Grid.Row="1" 
                 DataContext="{Binding VmUsedInputs, Mode=OneWay}" 
                 PropertyEditorTemplate="{StaticResource GridPropertyEditorTemplate}" />
    </Grid>
</UserControl>

入力のリストを表示するInputSelectControlを表すXAMLと、プロパティを編集するための「Popupの動作」が必要な各ListItemのContentControlプレースホルダー:

<UserControl x:Class="MyApp.InputSelectControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:props="clr-namespace:PopupButtonDependencyProp" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
  <Grid>
    <!-- Listbox holding our inputs. Assuming whatever we're contained in has 
         set our DataContext to a valid Input collection-->
    <ListBox x:Name="inputsUsed" Grid.Row="1" ItemsSource="{Binding}"         
             ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
             ScrollViewer.VerticalScrollBarVisibility="Auto" 
             SelectionMode="Multiple" ClipToBounds="True">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <Border x:Name="border" CornerRadius="7">
            <StackPanel VerticalAlignment="Stretch" Orientation="Horizontal">
               <!-- Input label-->
               <TextBlock Text="{Binding Path=Label}" FontWeight ="Bold"
                          FontSize ="12" FontStyle = "Normal" 
                          HorizontalAlignment="Stretch"
                          VerticalAlignment="Stretch" Margin="5,0,5,0" />
               <Expander x:Name="GridPropEditor" Header="Properties" 
                         Height="Auto" Margin="5,0,0,0" 
                         ToolTip="Open trace property dialog">
                  <!-- Properties button - The ContentControl below is rendering 
                       the PropertyEditorTemplate that was set by whoever contains us -->
                  <ContentControl  Template="{Binding PropertyEditorTemplate, 
                                   RelativeSource={RelativeSource AncestorType=props:InputSelectControl}}" />
                     </Expander>
            </StackPanel>
          </Border>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </UserControl>

ポップアップに表示するプロパティエディタテンプレートを挿入するためのDependencyPropertyを表すC#。

/// <summary>
/// Interaction logic for InputSelectControl.xaml
/// </summary>
public partial class InputSelectControl : UserControl
{
    #region Dependency Property stuff

    /// <summary>
    /// Dependency Property for control template to be rendered. This 
    /// lets us adorn the InputSelectControl with content in the Xaml. 
    /// The content can be different fore each instance of InputSelectControl.
    /// </summary>
    public static DependencyProperty PropertyEditorTemplateProperty =
        DependencyProperty.Register("PropertyEditorTemplate", 
                typeof(ControlTemplate), typeof(InputSelectControl));

    /// <summary>
    /// PropertyEditorTemplate. This is how the property is set and get by WPF
    /// </summary>
    public ControlTemplate PropertyEditorTemplate
    {
        get { return GetValue(PropertyEditorTemplateProperty) as ControlTemplate; }
        set { SetValue(PropertyEditorTemplateProperty, value); }
    }

    #endregion

    /// <summary>
    /// Constructor
    /// </summary>
    public InputSelectControl()
    {
        InitializeComponent();
    }
}

グリッドプロパティを編集するためのプレゼンテーションを説明するテンプレートであるGridInputPropertyEditorを表すXAML。これはグラフでは異なります。

<UserControl x:Class="MyApp.GridInputPropertyEditor"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

<Canvas Panel.ZIndex=”99”&gt;
    <!-- Property Editor Control - Assumes DataContext holds to the properties 
         that need to be edited-->
    <StackPanel Orientation="Vertical" Background="WhiteSmoke">

        <!-- Lists the properties for a Grid to be edited. We could use 
             any layout we need here. -->
        <ListBox ItemsSource="{Binding Properties}" Background="WhiteSmoke" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Margin="5,5">
                        <TextBlock Text="{Binding Label}" FontWeight="Bold"/>
                        <TextBlock Text=":" />
                        <TextBox Text="{Binding Value}" Margin="10,0" Width="20" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>
</Canvas>
</UserControl>

Snoopを使用すると、ListBoxアイテムのZ-Indexを高い数値に設定すると、プロパティエディターが前面に表示されることがわかりました。誰かがこれを回避するより良い方法を見つけたら、私に知らせてください。それ以外の場合は、選択したアイテムに基づいてzindexを上下させるトリガーを考え出すのに役立つ可能性があります。

4

1 に答える 1

0

さて、いくつかの試行錯誤の後、コードビハインドを使用して解決策を思いつくことができました。トリガーを使用してこれを行う方法を見つけることに興味がありますが、このアプローチで可能かどうかはわかりません。

更新プログラム エキスパンダー XAML は次のとおりです。

<Expander x:Name="GridPropEditor" Header="Properties" Height="Auto" Margin="5,0,0,0" 
          ToolTip="Open trace property dialog"
          Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                                         AncestorType={x:Type ListBoxItem}}}"
          PreviewMouseDown="GridPropEditor_PreviewMouseDown"  
          Expanded="GridPropEditor_Expanded">

xaml.cs ファイルに追加したコード ビハインドを次に示します。

//When an expander is expanded, collapse all the other expanders
private void GridPropEditor_Expanded(object sender, RoutedEventArgs e)
{
    if (ExpandersSelected == null)
        ExpandersSelected = new List<Expander>();

    var expander = (sender as Expander);
    var listbox = expander.Tag as ListBoxItem;

    if (!ExpandersSelected.Contains(expander))
        ExpandersSelected.Add(expander);

    if (ExpandersSelected != null)
    {
        foreach(var x in ExpandersSelected)
        {
            if (x.Equals(expander))
            {
                listbox.SetValue(Panel.ZIndexProperty, 99);
                continue;
            }   
            var l = x.Tag as ListBoxItem;
            x.IsExpanded = false;
            l.SetValue(Panel.ZIndexProperty, 0);
        }
    }
}

コード ビハインド ソリューションは、既に開いている可能性のあるすべてのエキスパンダーを閉じ、zindex を 99 に設定することで、現在展開されている Expanders コンテナーを前面に表示します。

繰り返しますが、誰かがより良い解決策を持っているなら、私はすべて耳にします。

于 2010-11-16T04:55:35.363 に答える