views:

146

answers:

1

Hi,

I've been trying to create my generic ReadOnlyCheckBox style/template but I'm having a problem with the binding to the data. In the example here:

http://stackoverflow.com/questions/921921/a-read-only-checkbox-in-c-wpf

you bind directly to the data from the ControlTemplate definition, but of course this is not really what I want, as I want to be able to declare the new checkbox something like this:

        <CheckBox x:Name="uiComboBox" Content="Does not set the backing property, but responds to it."
Style="{StaticResource ReadOnlyCheckBoxStyle}" IsChecked="{Binding MyBoolean}"  Click="uiComboBox_Click"/>

Except of course when I do this and then set the event trigger on the bullet to be a TemplateBinding of IsChecked I have exactly what I started with! I guess I don't understand why setting the binding directly in the bullet is different from setting IsChecked and then binding to that, isn't the TemplateBinding just a way of referencing what is set in the properties of the control being created? How is the Click triggering the UI update even tho the data does not get updated? Is there a trigger for Click I can override to stop the update?

I got all the DictionaryResource stuff working fine so I am happy with that, cheers for the pointer.

The other thing I was curious about was if it is possible to reduce my Control/Style template by using the BasedOn parameter in the style, then I would only override the things I actually need to change rather than declaring a lot of stuff that I think is part of the standard template anyway. I might have a play with this.

Cheers

ed

A: 

The problem you're running into is that you're trying to use DataBinding where you shouldn't.

I disagree with other answers you've been getting in the link you've posted. While the ControlTemplate solutions appear neat and tidy, they don't get at the heart of your problem, which is, you're trying to use a single control (a CheckBox) to do two different things: show state (e.g. checked/unchecked) and perform logic (remote device, etc.).

ControlTemplates are designed to change the way a control appears, but not behaves. You're trying to change behavior, not appearance. See "What Is a ControlTemplate?" here for more details

To do that, you're going to have to store some forego the standard binding and handle some events:

XAML:

<Window x:Class="WPFCheckBoxClickTester.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
     <CheckBox x:Name="foo" Checked="foo_Checked"></CheckBox>
    </Grid>
</Window>

Code-Behind:

using System.ComponentModel;
using System.Threading;
using System.Windows;

namespace WPFCheckBoxClickTester
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
     private BackgroundWorker _worker = new BackgroundWorker();

     public Window1()
     {
      InitializeComponent();

      foo.IsThreeState = false;
      this._worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
      this._worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
     }

     private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
     {
      foo.IsChecked = true;
      foo.IsEnabled = true;
      return;
     }

     private void _worker_DoWork(object sender, DoWorkEventArgs e)
     {
      Thread.Sleep(500);
      return;
     }

     private void foo_Checked(object sender, RoutedEventArgs e)
     {
      if( foo.IsChecked == true && this.foo.IsEnabled )
      {
       this.foo.IsChecked = false;
       this.foo.IsEnabled = false;

       this._worker.RunWorkerAsync();
      }
      return;
     }

    }
}

The above code example gives you the ability to execute some code async via BackgroundWorker -- I've put in a Thread.Sleep as a placeholder. I'm also using foo.IsEnabled as a sentinel value in foo_Checked, but you may need some extra state here to handle all of your cases (for instance, going from Checked to Unchecked).

micahtan
Hi Micahtan,Thanks for your response, I'm sorry it has taken me so long to get back to you but I got moved onto an urgent project that needed finishing.Although your answer could definately work it does not feel that elegant to me as the checkbox checks itself and then when handling the checked event we set it back, if you watch the button when you click you can see the check appear and then disappear again.Ideally I want to be able to edit the template to disable the checking when the click occurs so it only happens when I set it, or the bound variable takes a new value.cheersed
EdWaugh
Hi anyone on this thread, I solved my problem by creating a custom control based on button, see here:http://stackoverflow.com/questions/1088906/adding-a-custom-dependency-property-to-a-control-template-in-xamled
EdWaugh