从代码中获取WPF资源?

4

如何从代码中获取WPF资源是最简单的方式?

如果同一窗口中的复选框被选中,我需要禁用WPF表单中的文本框。我已经将复选框连接到代码后端的事件处理程序。事件处理程序将禁用复选框并将其背景更改为浅灰色,以表示该控件已被禁用:

private void OnCheckBoxChecked(object sender, RoutedEventArgs e)
{
    MyTextBox.IsEnabled = false;
    MyTextBox.Background = (Brush)FindResource("DisabledControlBackgroundBrush");
}

残障控件的背景颜色在资源字典中定义,并导入到WPF窗口中。我通过在XAML中设置文本框背景来测试资源,发现资源可以正常工作。
我知道事件处理程序也在工作,因为它在单击复选框时禁用文本框。
我的问题是,事件处理程序没有像应该改变Background属性。我怀疑我的FindResource调用存在问题,但我没有收到异常,并且输出窗口上没有任何信息。
那么,我该如何从代码中获取此资源并将其应用于我的文本框?感谢您的帮助。
2个回答

1
David。我已经使用TextBox.Style上的触发器,编写了一个示例窗口来实现这个功能。
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1">
    <Window.Resources>
        <SolidColorBrush x:Key="IsCheckedColor" Color="DarkGray"  />
    </Window.Resources>
    <StackPanel>
        <TextBox x:Name="textbox" Margin="36" Height="24"  >
            <TextBox.Style>
                <Style TargetType="TextBox">
                    <Setter Property="Background" Value="White" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsChecked, ElementName=checkbox}"  Value="True" >
                            <Setter Property="Background" Value="{StaticResource IsCheckedColor}"  />
                            <Setter Property="IsEnabled" Value="False" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBox.Style>
        </TextBox>
        <CheckBox x:Name="checkbox" Content="Click Me" Height="24" Margin="36"/>
    </StackPanel>
</Window>

你不能使用 Trigger 来改变另一个控件的属性,但是你可以使用它们来根据其他东西(比如 DataContext 或另一个控件)来改变控件的属性。

每个控件都可以有一个 Triggers 集合,但这只能包含 EventTriggers。在 Style 中,你可以使用普通的 Trigger 来控制动画,以及 DataTrigger,我在这个示例中使用了它来根据 CheckBox 的属性来控制 TextBox 的设置。

请注意,我还在 Triggers 集合之外使用了一个 Setter 来设置默认值,而且我不需要第二个 Setter 来处理当 CheckBox 没有被选中时的情况——它会回到“默认”状态。

编辑 - 如何更改禁用的 TextBox 的背景

我在Blend中完成这个操作,但如果你没有Blend,当然可以直接将XAML放入其中。这与控件状态有关。当TextBoxNormalMouseOverDisabled之间转换时,您可以动画地改变外观。在这种情况下,我们使用几乎为零的持续时间进行动画处理,因此更改是立即生效的。

将以下内容添加到StackPanel中:

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateGroup">
            <VisualState x:Name="Disabled">
                <Storyboard>
                    <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="textbox" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                        <SplineColorKeyFrame KeyTime="00:00:00" Value="{StaticResource IsCheckedColor}"/>
                    </ColorAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

感谢您对触发器的建议 - 我会接受这个答案。然而,标记似乎并不完全有效。显然,当您禁用文本框时,它会失去您分配给它的任何背景颜色。因此,我可以禁用文本框,但无法更改其背景颜色。 - David Veeneman
@David 我更新了答案,展示了当 TextBox 被禁用时如何更改其背景颜色。 - Jay

-1

这种方法是从Windows Forms中来的,对于WPF来说是一种不好的模式。你想做的一切都可以通过触发器和样式来完成。

 <Style x:Key="BackGroundCheckBoxStyle">  < !--apply the style to checkbox -->
  <Style.Triggers> 
   <Trigger Property="IsChecked" Value="True"> 
     <Setter Property="{Binding ElementName=m_txtBox, Path=IsEnabled, Mode=TwoWay}" Value="false}" /> 
     <!-- bind your resource here with a setter as well -->
     </Trigger> 
    </Style.Triggers> 
  </Style> 

将背景存储在应用程序资源范围或窗口中。触发器是可冻结对象,因此GUI会自动刷新(无需repaint())

尝试获取一些概述,因为这是一种开发应用程序的新方式 :)


1
这样做不起作用,并会导致运行时异常。您不能将绑定用于分配给Setter属性的值。 - John Bowen

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