2017-01-04 5 views
0

У нас есть ListBox с обычным ListBoxItemTemplate, который показывает некоторую информацию, используя свойство DisplayMemberPathListBox.Как установить всплывающую подсказку contentpresenter в значение, которое оно показывает?

ListBoxItemTemplate имеет внутри ContentPresenter.

Все, что нам нужно сделать, это установить свойство Tooltip для ContentPresenter, чтобы показать то же, что и ContentPresenter.

Я пытался сделать это:

<ContenPresenter Tooltip={Path Content, RelativeSource={RelativeSource Self}}/> 

Но я получаю контекст без DisplayMemberPath логики (весь объект DataContext).

Как я могу получить значение, указанное в ContentPresenter с применением «DisplayMemberPath»?

Заранее спасибо.

EDIT:

Вот стиль без подсказки (контроль поставил этот стиль и DisplayMemberPath свойства с переплетом):

<Style x:Key="CheckListBoxStyle" TargetType="{x:Type ListBox}" > 
    <Setter Property="SelectionMode" Value="Multiple" /> 
    <Setter Property="ItemContainerStyle" Value="{StaticResource CheckListBoxItemStyle}"/> 
    <Setter Property="Width" Value="177"/> 
    <Setter Property="HorizontalAlignment" Value="Left" /> 
    <Setter Property="Height" Value="70"/> 
</Style> 

<Style x:Key="CheckListBoxItemStyle" TargetType="{x:Type ListBoxItem}"> 
    <Setter Property="Background" Value="Transparent" /> 
    <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" /> 
    <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" /> 
    <Setter Property="Padding" Value="2,0,0,0" /> 
    <Setter Property="Template"> 

     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
       <Border x:Name="Bd" 
          Background="{TemplateBinding Background}" 
          BorderBrush="{TemplateBinding BorderBrush}" 
          BorderThickness="{TemplateBinding BorderThickness}" 
          Padding="{TemplateBinding Padding}" 
          SnapsToDevicePixels="true"> 
        <CheckBox HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
            VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
            IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Tag="CheckBox1"> 
         <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
        </CheckBox> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 
+0

Я не думаю, что можно использовать как свойство DisplayMemberPath и ItemTemplate для ListBox одновременно. Не могли бы вы показать свой код? –

+0

@ DTsawant: сделано. –

ответ

1

Как я могу получить значение, указанное в ContentPresenter с применением «DisplayMemberPath»?

Вы не можете делать это динамически в чистом XAML. Если вы знаете значение свойства DisplayMemberPath можно мог связать с этим свойством непосредственно:

<CheckBox HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                  IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Tag="CheckBox1" 
                  ToolTip="{Binding Path=Content.Name, ElementName=cp}"> 
    <ContentPresenter x:Name="cp" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
</CheckBox> 

Но вы не можете сделать что-то вроде ToolTip="{Binding Path=Content.[DisplayMemberPath], ElementName=cp}".

Для этого вам нужно будет написать код. Например, вы можете использовать конвертер:

public class ContentConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     string path = values[0] as string; 
     object dataObject = values[1]; 

     if(!string.IsNullOrEmpty(path) && dataObject != null) 
      return dataObject.GetType().GetProperty(path).GetValue(dataObject).ToString(); 

     return null; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

<ListBox x:Name="lb11" DisplayMemberPath="Name"> 
    <ListBox.Resources> 
     <local:ContentConverter x:Key="conv" /> 
    </ListBox.Resources> 
    <ListBox.Style> 
     <Style TargetType="{x:Type ListBox}" > 
      <Setter Property="SelectionMode" Value="Multiple" /> 
      <Setter Property="ItemContainerStyle"> 
       <Setter.Value> 
        <Style TargetType="{x:Type ListBoxItem}"> 
         <Setter Property="Background" Value="Transparent" /> 
         <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" /> 
         <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" /> 
         <Setter Property="Padding" Value="2,0,0,0" /> 
         <Setter Property="Template"> 
          <Setter.Value> 
           <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
            <Border x:Name="Bd" Background="{TemplateBinding Background}" 
                BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}" 
                Padding="{TemplateBinding Padding}" 
                SnapsToDevicePixels="true"> 
             <CheckBox HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                  IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Tag="CheckBox1"> 
              <CheckBox.ToolTip> 
               <MultiBinding Converter="{StaticResource conv}"> 
                <Binding Path="DisplayMemberPath" RelativeSource="{RelativeSource AncestorType=ListBox}"/> 
                <Binding Path="Content" ElementName="cp"/> 
               </MultiBinding> 
              </CheckBox.ToolTip> 
              <ContentPresenter x:Name="cp" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
             </CheckBox> 
            </Border> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </Setter.Value> 
      </Setter> 
      <Setter Property="Width" Value="177"/> 
      <Setter Property="HorizontalAlignment" Value="Left" /> 
      <Setter Property="Height" Value="70"/> 
     </Style> 
    </ListBox.Style> 
</ListBox> 
+0

Хорошо, спасибо. Я вижу вашу мысль. Я попытаюсь создать прикрепленное свойство, поскольку мне не нравятся использование конвертеров с объектами datacontext (content), так как похоже, что вы делаете что-то большее, чем визуальное преобразование. Спасибо, в любом случае! –

+0

Я использую отражение, чтобы получить значение свойства с динамическим именем из объекта данных. Вы не сможете избежать этого, если хотите использовать значение * string * DisplayMemberPath для получения фактического значения. – mm8

+0

Нет, все в порядке. Это вопрос разделения проблем. Я хочу сказать, что конвертер должен иметь только логику визуализации и передавать объект Datacontext в конвертер, тогда он выполняет логику VM. –

0

Так как вы определили ContentPresenter внутри шаблон , Вы не можете получить доступ к Контенту в привязке. Согласно DataContext распределения, вы уже в содержании level.so оно не работало, я думаю, изменение ContentPresenter к ContentControl и ToolTip как ниже будет работать

<ContentControl Tooltip={Binding}/> 

Поправьте меня, если я ошибаюсь.

+0

Добавление ContentControl внутри ControlTemplate не работает. Текст или инструментарий diplayed: \ –