2010-04-06 91 views
3

我想創建一個看起來像visual studio的簡單設計器。 具體來說,我希望我的項目具有與VS中相同的行爲:未選中時,會顯示一個簡單的標籤/文本塊,當它們被選中時,一個文本框允許我編輯該值。 這是實現這一目標的最佳方式?WPF:選中標籤到文本框

謝謝

回答

4

創建文本框控件模板和更改文本框的外觀,你喜歡當控制的重點也有內部的內容。

+0

簡單高效! 謝謝,正是我在尋找的! – fra 2010-04-06 11:37:20

0

我知道的太遲,但對於未來的觀衆:

該解決方案使用原來的TextBox控件模板,並增加了其與文本框的標籤屬性時文本框文本爲空替換Text屬性值的功能。這是相當複雜的造型,但它的作品! (無需任何代碼後面!!):

<Style x:Key="TextBoxPlaceHolder" BasedOn="{x:Null}" TargetType="{x:Type TextBox}"> 
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/> 
    <Setter Property="BorderThickness" Value="1"/> 
    <Setter Property="Padding" Value="1"/> 
    <Setter Property="AllowDrop" Value="true"/> 
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
    <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> 
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TextBox}"> 
       <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true"> 
        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
        </Microsoft_Windows_Themes:ListBoxChrome> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsEnabled" Value="false"> 
         <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/> 
         <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
        </Trigger> 
        <Trigger Property="IsFocused" Value="False"> 
         <Setter Property="Text"> 
          <Setter.Value> 
           <MultiBinding Converter="{StaticResource TextBoxPlaceHolderConverter}"> 
            <Binding RelativeSource="{RelativeSource Self}" Path="Text" /> 
            <Binding RelativeSource="{RelativeSource Self}" Path="Tag" /> 
           </MultiBinding> 
          </Setter.Value> 
         </Setter>         
        </Trigger> 
        <Trigger Property="IsFocused" Value="True"> 
         <Setter Property="Text"> 
          <Setter.Value> 
           <MultiBinding Converter="{StaticResource TextBoxPlaceHolderConverter}" ConverterParameter="True"> 
            <Binding RelativeSource="{RelativeSource Self}" Path="Text" /> 
            <Binding RelativeSource="{RelativeSource Self}" Path="Tag" /> 
           </MultiBinding> 
          </Setter.Value> 
         </Setter> 
        </Trigger> 
        <MultiDataTrigger> 
         <MultiDataTrigger.Conditions> 
          <Condition Value="True"> 
           <Condition.Binding> 
            <MultiBinding Converter="{StaticResource StringsEqualMultiConverter}" Mode="OneWay"> 
             <Binding RelativeSource="{RelativeSource Self}" Path="Text" /> 
             <Binding RelativeSource="{RelativeSource Self}" Path="Tag" /> 
            </MultiBinding> 
           </Condition.Binding> 
          </Condition> 
          <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsFocused}" Value="False"/> 
         </MultiDataTrigger.Conditions> 
         <Setter Property="Foreground" Value="#FF7C7C80"/> 
         <Setter Property="FontStyle" Value="Italic"/> 
        </MultiDataTrigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

和兩個提供轉換器:

public class TextBoxPlaceHolderConverter : IMultiValueConverter 
{ 
    private static object s_OriginalTag; 

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     s_OriginalTag = values[1]; 
     var actualText = values[0] as string; 
     var textToReturn = actualText ?? string.Empty; 
     var tagText = values[1] is string ? values[1] as string : null; 
     if (!(parameter is string && parameter.ToString() == "True")) 
     { 
      if (actualText != null && tagText != null) 
      { 
       if (actualText.Length == 0) // no text 
       { 
        textToReturn = tagText; 
       } 
       else 
       { 
        textToReturn = actualText; 
       } 
      } 
     } 
     else 
     { 
      if (actualText == tagText) 
      { 
       textToReturn = string.Empty; 
      } 
     } 

     return textToReturn; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     object[] toReturn = new object[2]; 
     toReturn[0] = value; 
     toReturn[1] = s_OriginalTag; 

     return toReturn; 
    } 
} 

public class StringsEqualMultiConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     var stringToCompare = string.Empty; 

     if (values != null) 
     { 
      if (values.Length > 0 && values[0] is string) 
      { 
       stringToCompare = values[0] as string; 
      } 
     } 

     var boolToReturn = values.Aggregate(true, (current, value) => current && (value is string && value.ToString().Equals(stringToCompare))); 
     return boolToReturn; 
    } 

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