tags:

views:

41

answers:

2

What is the simplest way to get a WPF resource from code?

I need to disable a text box in a WPF form if a checkbox in the same window is checked. I have wired the checkbox to an event handler in code-behind. The event handler disables the checkbox and changes its background to a light gray, to indicate that the control is disabled:

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

The disabled control background color is defined as a resource in a resource dictionary that is imported into the WPF window. I tested the resource by setting the textbox background in XAML, and the resource works fine.

I also know the event handler is working, because it disables the text box when the checkbox is clicked.

My problem is that the event handler isn't changing the Background property as it should. I suspect that there is a problem with my call to FindResource, but I am not getting an exception, and the Output window has nothing on it.

So, how do I get this resource from code and apply it to my text box? Thanks for your help.

A: 

this kind of approach is form Windows Forms which is a bad pattern for WPF. All what you want to do is can be done by triggers and styles Patten:

 <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> 

Background store in the Aplication.Resources scope or Window. Triggers are Freezable object so GUI will refresh itself (no repaint() needed)

Try to get some overview, since it is a new way to develop apps :)

lukas
This won't work and will give you a runtime exception. You can't use Bindings for values assigned to Setter's Property.
John Bowen
A: 

Hi, David. I've put together a sample window that does this using triggers on the 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>

You can't use a Trigger to change another control's properties, but you can use them to change a control's properties based on something else, like a DataContext or another control.

Each control can have a Triggers collection, but this can only contain EventTriggers. In a Style you can use plain Trigger which can be used to control animation, as well as DataTrigger, which I've used in this sample to control the TextBox settings based on the properties of the CheckBox.

Notice that I've also used a Setter outside of the Triggers collection to set the default value, and I don't need a second Setter for when the CheckBox is not checked -- it just goes back to the "default" state.

edit - how to change background of disabled TextBox

I do this in Blend, but if you don't have Blend you can of course put the XAML in directly. This has to do with controls states. As the TextBox transitions among Normal, MouseOver, and Disabled, you can animate changes to the appearance. In this case we use an animation of virtually zero duration, so the change is immediate.

Add the following to the 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>
Jay
Thanks for the suggestion on triggers--I'll accept the answer. However, the markup doesn't work completely. Apparently, when you disable a text box, it loses whatever background color you have assigned to it. So, I can disable the text box, but I can't change it's background color.
David Veeneman
@David I updated the answer to show how you can change the background color of the `TextBox` when it is disabled.
Jay