title: Set style for certain controls within window from contained usercontrol
body: <p>I have an application with multiple usercontrols that are used within certain windows. One of these usercontrols defines whether all other usercontrols in this window should allow editing, hence setting the <code>IsEnabled</code> property to <code>False</code> for all <code>CheckBox</code>es, <code>ComboBox</code>es and <code>Button</code>s. However, <code>TextBox</code>es should allow to copying their text, hence should not be disabled, but only read-only.</p>
  
  <p>I tried traversing the <code>LogicalTree</code>, but some self-built usercontrol does not have any property to disable them, but the controls contained within this usercontrol are only buttons and textboxes. That's why I tried applying a style to all changable elements (<code>CheckBox</code>, <code>ComboBox</code>, <code>Button</code> and <code>TextBox</code>), but it won't work.</p>
  
  <p>In the usercontrol's <code>Ressources</code> section I definded some styles:</p>
  
  <pre><code>&lt;Style TargetType="Control" x:Key="disabledStyle"&gt;
      &lt;Setter Property="IsEnabled" Value="False" /&gt;
  &lt;/Style&gt;
  &lt;Style TargetType="TextBox" x:Key="readOnlyStyle"&gt;
      &lt;Setter Property="IsReadOnly" Value="True" /&gt;
  &lt;/Style&gt;
  </code></pre>
  
  <p>And in CodeBehind, after checking the condition, I tried the following:</p>
  
  <pre><code># windowOwner is the root window containing this usercontrol
  for control in [Button, ComboBox, CheckBox]:
      if self.windowOwner.Resources.Contains(control):
          self.windowOwner.Resources.Remove(control)
      self.windowOwner.Resources.Add(control, self.Resources['disabledStyle'])
  
  if self.windowOwner.Resources.Contains(TextBox):
      self.windowOwner.Resources.Remove(TextBox)
  self.windowOwner.Resources.Add(TextBox, self.Resources['readOnlyStyle'])
  </code></pre>
  
  <p>But nothing happened. What am I doing wrong? Should I be doing it differently?</p>
  
  <p>=EDIT 1==================================================================</p>
  
  <p>I now tried the following, XAML:</p>
  
  <pre><code>&lt;Style x:Key="disabledStyle"&gt;
      &lt;!--&lt;Setter Property="Button.IsEnabled" Value="False" /&gt;
      &lt;Setter Property="CheckBox.IsEnabled" Value="False" /&gt;--&gt;
      &lt;Setter Property="ComboBox.IsEnabled" Value="False" /&gt;
      &lt;Setter Property="TextBox.IsReadOnly" Value="True" /&gt;
  &lt;/Style&gt;
  </code></pre>
  
  <p>CodeBehind:</p>
  
  <pre><code>self.windowOwner.Style = self.Resources['disabledStyle']
  </code></pre>
  
  <p>Suprisingly, even though the <code>IsEnabled</code> property is only set for <code>ComboBox</code>, everything is disabled. And if I only set the <code>TextBox.IsReadOnly</code> property nothing happens. Could someone explain this?</p>
  
  <p>=EDIT 2==================================================================</p>
  
  <p>I now also tried using a converter:</p>
  
  <p>(XAML)</p>
  
  <pre><code>&lt;Style TargetType="Control" x:Key="disabledStyle"&gt;
  &lt;Setter Property="IsEnabled" Value="False" /&gt;
  &lt;!--&lt;Setter Property="Button.IsEnabled" Value="False" /&gt;
  &lt;Setter Property="CheckBox.IsEnabled" Value="False" /&gt;
  &lt;Setter Property="ComboBox.IsEnabled" Value="False" /&gt; --&gt;
      &lt;Style.Triggers&gt;
          &lt;DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource typeConverter}}" Value="True"&gt;
              &lt;Setter Property="IsEnabled" Value="True" /&gt;
              &lt;Setter Property="TextBox.IsReadOnly" Value="True" /&gt;
          &lt;/DataTrigger&gt;
      &lt;/Style.Triggers&gt;
  &lt;/Style&gt;
  </code></pre>
  
  <p>(Converter)</p>
  
  <pre><code>public class TypeConverter : IValueConverter
  {
      public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
      {
          bool res = value.GetType() == typeof(TextBox);
          return res;
      }
  
      public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
      {    // Don't need any convert back
          return null;
      }
  }
  </code></pre>
  
  <p>But again, everything is just disabled (or nothing happens if you use the variant commented out).</p>
  
  <p>I got it working traversing the visual tree:</p>
  
  <pre><code>visited = set()
  
  def disableControls(control):
      visited.add(control)
      try:
          for childNumber in xrange(VisualTreeHelper.GetChildrenCount(control)):
              child = VisualTreeHelper.GetChild(control, childNumber)
  
              if hasattr(child, 'Content') and child.Content not in visited:
                  disableControls(child.Content)
              if type(child) in [Button, ComboBox, CheckBox]:
                  child.IsEnabled = False
              elif type(child) == TextBox:
                  child.IsReadOnly = True
              elif child not in visited:
                  disableControls(child)
      except:
          pass
  disableControls(self.windowOwner)
  </code></pre>
  
  <p>But I also would like to be able to later reset the changes to the original state. And that would mean I'd have to save all changes, which makes this far to complicated than it should be. I'm out of ideas.</p>