WPF:选中时将标签更改为文本框

3
我想创建一个简单的设计器,看起来像Visual Studio。 具体而言,我希望我的项目具有与VS相同的行为:当它们未被选中时,会显示一个简单的标签/文本块,当它们被选中时,文本框会让我编辑该值。 如何最好地实现这一点?
谢谢
2个回答

4
创建一个控件模板用于 TextBox,并在控件聚焦或其内部有内容时更改 TextBox 的外观。

简单而高效!谢谢,这正是我正在寻找的! - fra

0

我知道现在已经晚了,但是对于未来的读者:

这个解决方案使用原始的TextBox控件模板,并添加了一个功能,当文本框为空时,将Text属性值替换为TextBox的Tag属性。这是相当复杂的样式,但它可以工作!(没有任何代码后台!!):

<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();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接