防止只读文本框在Silverlight中变灰

时间:2009-06-24 23:41:02

标签: c# .net silverlight xaml

在Silverlight中,如何使IsReadOnly="True"的TextBox不会变灰。我的应用程序的灰色效果看起来很糟糕,我想禁用它,或者改变它的外观/颜色。

7 个答案:

答案 0 :(得分:11)

Silverlight 2中有几个选项,最简单的方法是使用TextBlock,因为它只是readonly。

如果你需要一个TextBox,那么你需要做的就是给它一个不起灰色效果的不同风格。

要做到这一点,打开混合。右键单击TextBox并选择Edit Control Parts(Template) - >编辑副本...无论您想要什么,都可以调用新样式。

然后,您想要编辑此新样式并删除名为“ReadOnlyVisualElement”的边框,并删除改变该边框的不透明度属性的故事板。

希望这有帮助。

添加了样式XAML

    <Style x:Key="ReadOnlyStyle" TargetType="TextBox">
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Background" Value="#FFFFFFFF"/>
        <Setter Property="Foreground" Value="#FF000000"/>
        <Setter Property="Padding" Value="2"/>
        <Setter Property="BorderBrush">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFA3AEB9" Offset="0"/>
                    <GradientStop Color="#FF8399A9" Offset="0.375"/>
                    <GradientStop Color="#FF718597" Offset="0.375"/>
                    <GradientStop Color="#FF617584" Offset="1"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                    <Grid x:Name="RootElement">
                        <vsm:VisualStateManager.VisualStateGroups>
                            <vsm:VisualStateGroup x:Name="CommonStates">
                                <vsm:VisualState x:Name="Normal"/>
                                <vsm:VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetName="MouseOverBorder" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)">
                                            <SplineColorKeyFrame KeyTime="0" Value="#FF99C1E2"/>
                                        </ColorAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="ReadOnly">
                                    <Storyboard>
                                    </Storyboard>
                                </vsm:VisualState>
                            </vsm:VisualStateGroup>
                            <vsm:VisualStateGroup x:Name="FocusStates">
                                <vsm:VisualState x:Name="Focused">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="Unfocused">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
                                            <SplineDoubleKeyFrame KeyTime="0" Value="0"/>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                            </vsm:VisualStateGroup>
                            <vsm:VisualStateGroup x:Name="ValidationStates">
                                <vsm:VisualState x:Name="Valid"/>
                                <vsm:VisualState x:Name="InvalidUnfocused">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                                <vsm:VisualState x:Name="InvalidFocused">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ValidationErrorElement" Storyboard.TargetProperty="Visibility">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsOpen">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <System:Boolean>True</System:Boolean>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </vsm:VisualState>
                            </vsm:VisualStateGroup>
                        </vsm:VisualStateManager.VisualStateGroups>
                        <Border x:Name="Border" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1">
                            <Grid>
                                <Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
                                    <ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>
                                </Border>
                            </Grid>
                        </Border>
                        <Border x:Name="DisabledVisualElement" IsHitTestVisible="False" Opacity="0" Background="#A5F7F7F7" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}"/>
                        <Border x:Name="FocusVisualElement" Margin="1" IsHitTestVisible="False" Opacity="0" BorderBrush="#FF6DBDD1" BorderThickness="{TemplateBinding BorderThickness}"/>
                        <Border x:Name="ValidationErrorElement" Visibility="Collapsed" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1">
                            <ToolTipService.ToolTip>
                                <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                                    <ToolTip.Triggers>
                                        <EventTrigger RoutedEvent="Canvas.Loaded">
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsHitTestVisible">
                                                        <DiscreteObjectKeyFrame KeyTime="0">
                                                            <DiscreteObjectKeyFrame.Value>
                                                                <System:Boolean>true</System:Boolean>
                                                            </DiscreteObjectKeyFrame.Value>
                                                        </DiscreteObjectKeyFrame>
                                                    </ObjectAnimationUsingKeyFrames>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </EventTrigger>
                                    </ToolTip.Triggers>
                                </ToolTip>
                            </ToolTipService.ToolTip>
                            <Grid Height="12" HorizontalAlignment="Right" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12" Background="Transparent">
                                <Path Fill="#FFDC000C" Margin="1,3,0,0" Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z"/>
                                <Path Fill="#ffffff" Margin="1,3,0,0" Data="M 0,0 L2,0 L 8,6 L8,8"/>
                            </Grid>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

我会看到Blend的预览,手动编写上面的内容会有大量不必要的工作。

答案 1 :(得分:10)

似乎没有任何东西在xaml中工作(像往常一样),所以我提出的最佳解决方案就是在没有IsReadOnly属性的情况下自己创建一个文本框。

public class ReadOnlyTextBox : TextBox
{
    protected override void OnKeyDown(KeyEventArgs e)
    {
        e.Handled = true;
        base.OnKeyDown(e);
    }
}

答案 2 :(得分:3)

如果您只想要HTML中的等效文本块,可以选择(由于某种原因,甚至缺少Silverlight 4),您可以稍微缩短Graeme的答案:

<Style x:Key="ReadOnlyStyle" TargetType="TextBox">
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Background" Value="#FFFFFFFF"/>
    <Setter Property="Padding" Value="2"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid x:Name="RootElement">
                    <vsm:VisualStateManager.VisualStateGroups>
                        <vsm:VisualStateGroup x:Name="CommonStates">
                            <vsm:VisualState x:Name="Normal"/>
                            <vsm:VisualState x:Name="MouseOver"/>
                            <vsm:VisualState x:Name="Disabled" />
                            <vsm:VisualState x:Name="ReadOnly"/>
                        </vsm:VisualStateGroup>
                        <vsm:VisualStateGroup x:Name="FocusStates">
                            <vsm:VisualState x:Name="Focused">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
                                        <SplineDoubleKeyFrame KeyTime="0" Value="1"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="Unfocused">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity">
                                        <SplineDoubleKeyFrame KeyTime="0" Value="0"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                        </vsm:VisualStateGroup>
                    </vsm:VisualStateManager.VisualStateGroups>
                    <Border x:Name="Border" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1">
                        <Grid>
                            <Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
                                <ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>
                            </Border>
                        </Grid>
                    </Border>
                    <Border x:Name="DisabledVisualElement" IsHitTestVisible="False" Opacity="0" Background="#A5F7F7F7" BorderBrush="#A5F7F7F7" BorderThickness="{TemplateBinding BorderThickness}"/>
                    <Border x:Name="FocusVisualElement" Margin="1" IsHitTestVisible="False" Opacity="0" BorderBrush="#FF6DBDD1" BorderThickness="{TemplateBinding BorderThickness}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

您甚至可以删除已禁用的状态。

答案 3 :(得分:2)

这是@Struan答案的增强版。

如果您想要一个只读文本框,我假设您要允许Select allCopy。您需要处理Ctrl+ACtrl+C等按键。

免责声明:这不是一套完整的密钥 - 您可能需要添加更多密钥,但至少可以进行复制。

public class ReadOnlyTextBox : TextBox
{
    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Up || e.Key == Key.Down)
        {
            base.OnKeyDown(e);
            return;
        }

        if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control ||
            (Keyboard.Modifiers & ModifierKeys.Apple) == ModifierKeys.Apple)
        {
            if (e.Key == Key.A || e.Key == Key.C)
            {
                // allow select all and copy!
                base.OnKeyDown(e);
                return;
            }
        }

        e.Handled = true;
        base.OnKeyDown(e);
    }
}

这是一个我正在使用的简单样式,它向用户表明该项目是可选的,但比典型的文本框小。

<Style TargetType="my:ReadOnlyTextBox">
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Padding" Value="3,0,3,0"/>
    <Setter Property="Background" Value="Transparent"/>
</Style>

答案 4 :(得分:0)

我发现@ Simon_Weaver的解决方案最容易实现。我做的唯一改变是检查Key.Tab以及左/右/上/下,以便我可以跳出字段。我创建了类 ReadOnlyTextBox 并复制了上面的代码。然后我添加了Key.Tab的检查并编译。接下来,我从

更改了我的Xaml标签
<TextBox ... IsEnabled="False" />

<MyNameSpace:ReadOnlyTextBox ... Background="LightGray" />

(删除IsEnabled引用并添加背景颜色)。它的外观和工作完全符合我的预期。

谢谢西蒙。

答案 5 :(得分:0)

我希望将样式简化为裸骨,并使用silverlight 4.0进行测试:

<Style x:Key="ReadOnlyStyle" TargetType="TextBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <TextBlock Text="{TemplateBinding Text}"  TextAlignment="{TemplateBinding TextAlignment}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这几乎是一种欺骗,就像说:Hey silverligh, this textbox is a textblock! 您最终应该在TextBlock标记中添加一些内容,以更好地反映其他TextBox属性。

答案 6 :(得分:0)

在按钮的定义/行为/外观发生变化之前,另一个更优雅的解决方案是简单地将TextBox更改为Button。将“文本”属性更改为“内容”属性以设置显示的文本,删除“IsReadOnly”设置,您将获得所需的效果,我相信(类似于文本框的平面控件支持文本和所有边框,背景,没有不透明度变化的TextBox的前景属性[灰化]和定义新样式的麻烦)。

当用户尝试与此控件进行交互时,它的功能会在click事件中发生更改,但如果没有与该按钮关联的事件处理程序,则不会对您的界面产生任何影响。事实上,我认为默认按钮行为会使效果看起来有点“酷”。