从包含的usercontrol设置窗口内某些控件的样式

cau*_*ima 11 c# wpf xaml user-controls ironpython

我有一个应用程序具有在某些窗口中使用的多个用户控件.其中一个用户控件定义此窗口中的所有其他用户控件是否应允许编辑,因此将IsEnabled属性设置False为所有CheckBoxes,ComboBoxes和Buttons.但是,TextBoxes应该允许复制它们的文本,因此不应该被禁用,而只能是只读的.

我试过遍历LogicalTree,但是一些自建的usercontrol没有任何属性来禁用它们,但是这个usercontrol中包含的控件只是按钮和文本框.这就是为什么我想申请一个风格多变的所有元素(CheckBox,ComboBox,ButtonTextBox),但它不会工作.

在usercontrol的Ressources部分中,我定义了一些样式:

<Style TargetType="Control" x:Key="disabledStyle">
    <Setter Property="IsEnabled" Value="False" />
</Style>
<Style TargetType="TextBox" x:Key="readOnlyStyle">
    <Setter Property="IsReadOnly" Value="True" />
</Style>
Run Code Online (Sandbox Code Playgroud)

在CodeBehind中,在检查条件后,我尝试了以下方法:

# 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'])
Run Code Online (Sandbox Code Playgroud)

但什么都没发生.我究竟做错了什么?我应该采用不同的方式吗?

=编辑1 =============================================== ===================

我现在尝试了以下,XAML:

<Style x:Key="disabledStyle">
    <!--<Setter Property="Button.IsEnabled" Value="False" />
    <Setter Property="CheckBox.IsEnabled" Value="False" />-->
    <Setter Property="ComboBox.IsEnabled" Value="False" />
    <Setter Property="TextBox.IsReadOnly" Value="True" />
</Style>
Run Code Online (Sandbox Code Playgroud)

代码隐藏:

self.windowOwner.Style = self.Resources['disabledStyle']
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,即使该IsEnabled物业仅适用于此,ComboBox一切都被禁用.如果我只设置TextBox.IsReadOnly属性没有任何反应.有人可以解释一下吗?

=编辑2 =============================================== ===================

我现在也尝试使用转换器:

(XAML)

<Style TargetType="Control" x:Key="disabledStyle">
<Setter Property="IsEnabled" Value="False" />
<!--<Setter Property="Button.IsEnabled" Value="False" />
<Setter Property="CheckBox.IsEnabled" Value="False" />
<Setter Property="ComboBox.IsEnabled" Value="False" /> -->
    <Style.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource typeConverter}}" Value="True">
            <Setter Property="IsEnabled" Value="True" />
            <Setter Property="TextBox.IsReadOnly" Value="True" />
        </DataTrigger>
    </Style.Triggers>
</Style>
Run Code Online (Sandbox Code Playgroud)

(转换器)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但同样,一切都被禁用(如果您使用已注释的变体,则没有任何反应).

我让它遍历可视树:

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)
Run Code Online (Sandbox Code Playgroud)

但我也希望以后能够将更改重置为原始状态.这意味着我必须保存所有更改,这使得这远远应该是复杂的.我没有想法.

cau*_*ima 1

我让它以一种不太优雅的方式工作,迭代所有控件并自己设置属性。在执行此操作时,我保存了有关更改哪些控件的信息,以便能够将 UI 重置为原始状态。我对此不太满意,但它似乎有效。我更喜欢设置和取消设置某些样式,但我没有找到这样做的方法。

这是我最终使用的内容,但请随意发布更好的内容。首先是禁用部分:

visited = set()

def disableControls(control):
    visited.add(control)

    for childNumber in xrange(VisualTreeHelper.GetChildrenCount(control)):
        child = VisualTreeHelper.GetChild(control, childNumber)

        # save the old state
        if type(child) in [Button, ComboBox, CheckBox] and child.IsEnabled:
            child.IsEnabled = False
            self.disabledControls.add(child)
        elif type(child) == TextBox and not child.IsReadOnly:
            child.IsReadOnly = True
            self.disabledControls.add(child)
        elif child not in visited:
            disableControls(child)
disableControls(self.windowOwner)
Run Code Online (Sandbox Code Playgroud)

这是将 UI“重置”到原始状态的部分:

while self.disabledControls:
    child = self.disabledControls.pop()
    if type(child) in [Button, ComboBox, CheckBox]:
        child.IsEnabled = True
    elif type(child) == TextBox:
        child.IsReadOnly = False
Run Code Online (Sandbox Code Playgroud)

-setvisited只是一个局部变量,以避免多次访问控件,这对于某些网格来说很奇怪。-setdisabledControls保存所有未禁用的控件,因此已被代码禁用,并且当 UI 应将其自身重置为原始状态时必须重置。