2016-10-13 14 views
0

私は、各アイテム(お気に入りとお気に入りではありません)がラベル+ボタンであるカスタムコンボボックスを持っています。最後のアイテムにはすべての要素をロードするボタンしかありません。今、私は最初の項目としてヘッダーを追加したい、それは "お気に入り"と言います。WPFカスタムコンボボックスにヘッダーを追加

今私が持っている:

私は空のインターフェースIDrawableを作成:

<ComboBox 
     x:Name="ComboBoxBtn" 
     VerticalAlignment="Top" 
     HorizontalAlignment="Left" 
     Margin="0,0,0,-1" 
     Width="300" 
     ItemsSource="{Binding Source, RelativeSource={RelativeSource AncestorType=UserControl}}" 
     SelectedItem="{Binding Path=Selected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=UserControl}}" 
     IsSynchronizedWithCurrentItem="True">   
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <Grid Name="PART_GRID"> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="3*" /> 
         <ColumnDefinition Width="Auto" /> 
        </Grid.ColumnDefinitions> 
        <Label 
         Content="{Binding}" 
         Width="250" Visibility="{Binding Path=., Converter={StaticResource elementToVisibilityConverter}}" /> 
        <Button Name="PART_BUTTON" 
         Grid.Column="1" 
         Content="+" 
         Command="{Binding AddCommandButton, ElementName=root}" 
         CommandParameter="{Binding}" 
         Visibility="{Binding Path=., Converter={StaticResource elementToVisibilityConverter}}"/> 
        <Button Content="Carregar Todos" Margin="5,5" 
            Command="{Binding LoadAllCommandButton, ElementName=root}" 
            CommandParameter="{Binding ElementName=root, Path=FavoriteType}" 
            Visibility="{Binding Path=.,Converter={StaticResource elementToVisibilityForAddConverter}}"/> 
       </Grid> 
       <DataTemplate.Triggers> 
        <DataTrigger Binding="{Binding Favorite}" 
          Value="True"> 
         <Setter TargetName="PART_GRID" 
          Property="Background" 
          Value="#FFE6E6FA" /> 
         <Setter TargetName="PART_BUTTON" 
          Property="Content" 
          Value="-" /> 
         <Setter TargetName="PART_BUTTON" 
          Property="Command" 
          Value="{Binding RemoveCommandButton, ElementName=root}" /> 
        </DataTrigger> 
       </DataTemplate.Triggers> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 
+3

Mygridを置き換え[前回](のhttp:/ /stackoverflow.com/a/39997414/4838058)。ボタンのある行の代わりに、ScrollViewer(ItemsPresenterを含む)の行の前にlabelを含む行を追加します。 – Funk

答えて

1

私は私がより簡単できれいだと思い異なるaproachを、好適。
mylabelという:

public class MyLabel : IDrawable 
{ 
    public string text { get; set; } 
    public MyLabel() 
    { 
     this.text = "MYTEXT"; 
    } 
} 

にMyButton:

public class MyButton : IDrawable 
{ 
    public string text { get; set; } 
    public MyButton() 
    { 
     this.text = "MYNBUTTON"; 
    } 
} 

MyLabelButton: パブリッククラス すべてのクラスは、私はこれらを作成しIDrawable から継承する必要がありますコンボボックスの内側に配置する必要がありますMyLabelButton:IDrawable { public string labelText {get;セット; } 公開ストリングbuttonText {get;セット;あなたは、私が標準コンボボックスとカスタム要素を持って見ることができるように

public partial class MainWindow : Window 
    { 
     private IDrawable clicked; 

     public ObservableCollection<IDrawable> list { get; set; } 
     public IDrawable sel { get; set; } 

     public MainWindow() 
     { 
      InitializeComponent(); 
      list = new ObservableCollection<IDrawable>(); 
      list.Add(new MyLabel()); 
      list.Add(new MyLabelButton()); 
      list.Add(new MyButton()); 
      this.DataContext = this; 
     } 

     private void ComboBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 
      Point pt = e.GetPosition(MyGrid); 

      clicked = null; 
      VisualTreeHelper.HitTest(
       MyGrid, 
       null, 
       new HitTestResultCallback(ResultCallback), 
       new PointHitTestParameters(pt)); 


      if (clicked != null) 
      { 
       ((ComboBox)sender).IsDropDownOpen = false; 

       //do something 
      } 
     } 

     private HitTestResultBehavior ResultCallback(HitTestResult result) 
     { 
      DependencyObject parentObject = VisualTreeHelper.GetParent(result.VisualHit); 

      if (parentObject == null) 
       return HitTestResultBehavior.Continue; 

      var v = parentObject as Button; 

      if (v == null) 
       return HitTestResultBehavior.Continue; 

      if (v.DataContext != null && v.DataContext is IDrawable) 
      { 
       clicked = (IDrawable)v.DataContext; 
       return HitTestResultBehavior.Stop; 
      } 
      return HitTestResultBehavior.Continue; 
     } 
    } 

結果がthis

です:}ここより

public MyLabelButton() 
    { 
     labelText = "labelText"; 
     buttonText = "buttonText"; 
    } 
} 

は、XAML

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:me="clr-namespace:WpfApplication1"> 
    <Window.Resources> 
     <DataTemplate DataType="{x:Type me:MyButton}"> 
      <Button Content="{Binding text}" /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type me:MyLabel}"> 
      <TextBlock Text="{Binding text}"/> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type me:MyLabelButton}"> 
      <StackPanel Orientation="Horizontal"> 
       <Label Content="{Binding labelText}"/> 
       <Button Content="{Binding buttonText}"/> 
      </StackPanel> 
     </DataTemplate> 
    </Window.Resources> 
    <Grid Name="MyGrid"> 
     <ComboBox Name="MyCombo" ItemsSource="{Binding list}" SelectedItem="{Binding sel}" PreviewMouseLeftButtonUp="ComboBox_PreviewMouseLeftButtonUp"/> 
    </Grid> 
</Window> 

と分離コードです。それはより良いと思う。コードビハインドでは、最初のラベルを選択できない、ボタンに関連付けられたコマンドを呼び出す、ボタンが押された場合など、すべてを処理できます。

ComboBox_PreviewMouseLeftButtonUp選択したボタンを押しても何か特別な操作をしたい場合は、選択したアイテムのクリックを処理し、ドロップダウンメニューを表示しません。

この例はかなりベアボーンです。少しカスタマイズして、どこでもMVVMを使用する必要があります。
ドロップダウンメニューでボタンを押すことができる瞬間に、そのボタンが選択されていなければ、クリックを無効にすることができます。

EDIT

ComboBox_PreviewMouseLeftButtonUp次のようにする必要があります:

private void ComboBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 
      Point pt = e.GetPosition((ComboBox)sender); 

      clicked = null; 
      VisualTreeHelper.HitTest(
       (ComboBox)sender, 
       null, 
       new HitTestResultCallback(ResultCallback), 
       new PointHitTestParameters(pt)); 


      if (clicked != null) 
      { 
       ((ComboBox)sender).IsDropDownOpen = false; 

       //do something 
      } 
     } 

(あなたが同じ方法でこれを行うことができるはず(ComboBox)sender

関連する問題