从包含的用户控件中为 window 内的某些控件设置样式
Set style for certain controls within window from contained usercontrol
我有一个包含多个用户控件的应用程序,这些控件在某些 windows 中使用。这些用户控件之一定义此 window 中的所有其他用户控件是否应允许编辑,因此将所有 CheckBox
的 IsEnabled
属性 设置为 False
,ComboBox
es 和 Button
s。然而,TextBox
es 应该允许复制他们的文本,因此不应该被禁用,而只是只读的。
我尝试遍历LogicalTree
,但是一些自建的用户控件没有任何属性禁用它们,但是这个用户控件中包含的控件只有按钮和文本框。这就是为什么我尝试将样式应用于所有可变元素(CheckBox
、ComboBox
、Button
和 TextBox
),但它不起作用。
在用户控件的 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>
在 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'])
但是什么也没发生。我究竟做错了什么?我应该采取不同的做法吗?
=编辑 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>
代码隐藏:
self.windowOwner.Style = self.Resources['disabledStyle']
令人惊讶的是,尽管 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>
(转换器)
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;
}
}
但同样,所有内容都被禁用(或者如果您使用注释掉的变体则什么也不会发生)。
我在遍历可视化树时得到了它:
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)
但我也希望以后能够将更改重置为原始状态。这意味着我必须保存所有更改,这使得这比它应该的复杂得多。我没主意了。
我认为删除样式并添加新样式不会通知控件应用新样式。
您应该直接在控件上设置样式,例如:
self.MyControl.Style = self.Resources['readOnlyStyle'] as Style
语法可能不同,但我是 C# 专家。
您可能无法通过使用 self.Resources['disabledStyle']
获取资源(当在控件层次结构中定义样式时通常会这样做)。它可以给你 null 并且可能不会注意到它。
尝试
MyControl.Style = DirectCast(FindResource("labelStyle2"), Style)
FindResource() 如果找不到所请求的资源,将会报错。
您好,请尝试下一个:
XAML
<Window x:Class="ListViewWithCanvasPanel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:listViewWithCanvasPanel="clr-namespace:ListViewWithCanvasPanel"
Title="MainWindow" Height="350" Width="525" x:Name="This" ResizeMode="CanResize"
listViewWithCanvasPanel:Attached.AreChildrenEnabled = "true"><!--put your content here--></Window>
附加属性代码
public class Attached
{
public static readonly DependencyProperty AreChildrenEnabledProperty = DependencyProperty.RegisterAttached("AreChildrenEnabled", typeof (bool), typeof (Attached), new PropertyMetadata(default(bool), AreChildrenEnabledPropertyChangedCallback));
private static void AreChildrenEnabledPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var val = (bool) args.NewValue;
if (val == false)
{
var visual = dependencyObject as FrameworkElement;
if (visual == null) return;
visual.Loaded -= VisualOnLoaded;
visual.Unloaded -= VisualOnUnloaded;
}
else
{
var visual = dependencyObject as FrameworkElement;
if(visual == null) return;
visual.Loaded += VisualOnLoaded;
visual.Unloaded += VisualOnUnloaded;
}
}
private static void VisualOnUnloaded(object sender, RoutedEventArgs e)
{
var visual = sender as FrameworkElement;
if (visual == null) return;
visual.Loaded -= VisualOnLoaded;
}
private static void VisualOnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var visual = sender as FrameworkElement;
if (visual == null) return;
var list = visual.GetAllVisualChildren();
Debug.WriteLine("children count on loading: {0}", list.Count);
var actionOnChildrenLoading = GetActionOnEachLoadedVisualChild(visual);
if(actionOnChildrenLoading == null) return;
list.ForEach(o =>
{
var combo = o as ComboBox;
if (combo != null)
{
combo.IsEnabled = false;
}
var button = o as Button;
if (button != null)
{
button.IsEnabled = false;
}
var textBlock = o as TextBlock;
if (textBlock != null)
{
textBlock.IsEnabled = false;
}
var cb = o as CheckBox;
if (cb != null)
{
cb.IsEnabled = false;
}
var textBox = o as TextBox;
if (textBox == null) return;
textBox.IsEnabled = true;
textBox.IsReadOnly = true;
});
}
public static readonly DependencyProperty ActionOnEachLoadedVisualChildProperty = DependencyProperty.RegisterAttached(
"ActionOnEachLoadedVisualChild", typeof (Action<DependencyObject>), typeof (Attached), new PropertyMetadata(default(Action<DependencyObject>)));
public static void SetActionOnEachLoadedVisualChild(DependencyObject element, Action<DependencyObject> value)
{
element.SetValue(ActionOnEachLoadedVisualChildProperty, value);
}
public static Action<DependencyObject> GetActionOnEachLoadedVisualChild(DependencyObject element)
{
return (Action<DependencyObject>) element.GetValue(ActionOnEachLoadedVisualChildProperty);
}
public static bool GetAreChildrenEnabled(UIElement element)
{
return (bool) element.GetValue(AreChildrenEnabledProperty);
}
public static void SetAreChildrenEnabled(UIElement element, bool value)
{
element.SetValue(AreChildrenEnabledProperty, value);
}
}
帮手代码
public static class VisualTreeHelperExtensions
{
public static T FindParent<T>(this DependencyObject child) where T : DependencyObject
{
while (true)
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
child = parentObject;
}
}
public static List<DependencyObject> GetAllVisualChildren(this DependencyObject parent)
{
var resultedList = new List<DependencyObject>();
var visualQueue = new Queue<DependencyObject>();
visualQueue.Enqueue(parent);
do
{
var depObj = visualQueue.Dequeue();
var childrenCount = VisualTreeHelper.GetChildrenCount(depObj);
for (int i = 0; i < childrenCount; i++)
{
var v = VisualTreeHelper.GetChild(depObj, i);
visualQueue.Enqueue(v);
}
resultedList.Add(depObj);
} while (visualQueue.Count > 0);
resultedList.RemoveAt(0);
return resultedList;
}
}
**简短说明:*
找到您根的所有视觉子项(例如window),扫描它们并根据子项类型执行操作。
此致,
我让它以一种不太优雅的方式工作,遍历所有控件并自己设置 属性。在这样做的同时,我保存了关于我更改了哪些控件以便能够将 UI 重置为原始状态的信息。我对此不是很满意,但它似乎有效。我更喜欢设置和取消设置一些样式,但我没有找到这样做的方法。
这是我最终使用的,但随时 post 更好的东西。首先是禁用部分:
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)
这里是 "reset" 和 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
visited
-set 只是一个局部变量,以避免多次访问控件,这种情况很奇怪,例如对于一些网格。 disabledControls
-set 包含所有未禁用的控件,因此已被代码禁用,并且在 UI 应将其自身重置为原始状态时必须重置。
试试这个,
1.Add 一个布尔值 属性 对用户控件说 CanUserEdit,它控制可以在其他控件中编辑的内容。
2.Add 其他用户控件中的数据触发器并绑定到 CanUserEdit(2 个数据触发器,1 个用于组合框,另一个用于文本框)。
在其中定义没有 key.this 方式的 UserControl 标签,它将影响该用户控件中存在的所有文本框和组合框。
您还将获得集中控制。
示例代码:-
在每个 userControl.
中添加 CanUserEdit 依赖项 属性
//Replace MainUserControl with your control name
public static readonly DependencyProperty CanUserEditProperty =
DependencyProperty.Register("CanUserEdit", typeof(bool),
typeof(MainUserControl));
public bool CanUserEdit
{
get { return (bool)GetValue(CanUserEditProperty); }
set { SetValue(CanUserEditProperty, value); }
}
在包含文本框和组合框的用户控件中,您可以将以下代码添加到 UserControl.Resources
<UserControl.Resources>
<Style TargetType="TextBox">
<Setter Property="IsReadOnly" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding CanUserEdit}" Value="false">
<Setter Property="IsReadOnly" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="ComboBox">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding CanUserEdit}" Value="false">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
这将影响该控件内的所有组合框和文本框。
并且在您的主窗口中,您将每个 UserControl 的 CanUserEdit 属性 绑定到具有编辑控制权的 UserControl 的 CanUserEdit 属性。
示例(MainUserControl 是具有文本框和组合框的控件):
<local:MainUserControl CanUserEdit="{Binding CanUserEdit,ElementName=CanUserEditControl}" />
现在您只需切换控制编辑的 UserControl 的 CanUserEdit 属性,所有控件都会受到影响。
实现此方案的一种简单方法是通过发布者订阅者实现。将 属性 状态发布到其他用户控件并通过 binding/assigning 将控件状态设置为 属性 到目标控件很容易。
我通过 MvvmLight Messenger 实现了类似的场景,我什至根据一些内部控制状态禁用了一些功能区命令。
我有一个包含多个用户控件的应用程序,这些控件在某些 windows 中使用。这些用户控件之一定义此 window 中的所有其他用户控件是否应允许编辑,因此将所有 CheckBox
的 IsEnabled
属性 设置为 False
,ComboBox
es 和 Button
s。然而,TextBox
es 应该允许复制他们的文本,因此不应该被禁用,而只是只读的。
我尝试遍历LogicalTree
,但是一些自建的用户控件没有任何属性禁用它们,但是这个用户控件中包含的控件只有按钮和文本框。这就是为什么我尝试将样式应用于所有可变元素(CheckBox
、ComboBox
、Button
和 TextBox
),但它不起作用。
在用户控件的 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>
在 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'])
但是什么也没发生。我究竟做错了什么?我应该采取不同的做法吗?
=编辑 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>
代码隐藏:
self.windowOwner.Style = self.Resources['disabledStyle']
令人惊讶的是,尽管 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>
(转换器)
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;
}
}
但同样,所有内容都被禁用(或者如果您使用注释掉的变体则什么也不会发生)。
我在遍历可视化树时得到了它:
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)
但我也希望以后能够将更改重置为原始状态。这意味着我必须保存所有更改,这使得这比它应该的复杂得多。我没主意了。
我认为删除样式并添加新样式不会通知控件应用新样式。
您应该直接在控件上设置样式,例如:
self.MyControl.Style = self.Resources['readOnlyStyle'] as Style
语法可能不同,但我是 C# 专家。
您可能无法通过使用 self.Resources['disabledStyle']
获取资源(当在控件层次结构中定义样式时通常会这样做)。它可以给你 null 并且可能不会注意到它。
尝试
MyControl.Style = DirectCast(FindResource("labelStyle2"), Style)
FindResource() 如果找不到所请求的资源,将会报错。
您好,请尝试下一个:
XAML
<Window x:Class="ListViewWithCanvasPanel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:listViewWithCanvasPanel="clr-namespace:ListViewWithCanvasPanel"
Title="MainWindow" Height="350" Width="525" x:Name="This" ResizeMode="CanResize"
listViewWithCanvasPanel:Attached.AreChildrenEnabled = "true"><!--put your content here--></Window>
附加属性代码
public class Attached
{
public static readonly DependencyProperty AreChildrenEnabledProperty = DependencyProperty.RegisterAttached("AreChildrenEnabled", typeof (bool), typeof (Attached), new PropertyMetadata(default(bool), AreChildrenEnabledPropertyChangedCallback));
private static void AreChildrenEnabledPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var val = (bool) args.NewValue;
if (val == false)
{
var visual = dependencyObject as FrameworkElement;
if (visual == null) return;
visual.Loaded -= VisualOnLoaded;
visual.Unloaded -= VisualOnUnloaded;
}
else
{
var visual = dependencyObject as FrameworkElement;
if(visual == null) return;
visual.Loaded += VisualOnLoaded;
visual.Unloaded += VisualOnUnloaded;
}
}
private static void VisualOnUnloaded(object sender, RoutedEventArgs e)
{
var visual = sender as FrameworkElement;
if (visual == null) return;
visual.Loaded -= VisualOnLoaded;
}
private static void VisualOnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var visual = sender as FrameworkElement;
if (visual == null) return;
var list = visual.GetAllVisualChildren();
Debug.WriteLine("children count on loading: {0}", list.Count);
var actionOnChildrenLoading = GetActionOnEachLoadedVisualChild(visual);
if(actionOnChildrenLoading == null) return;
list.ForEach(o =>
{
var combo = o as ComboBox;
if (combo != null)
{
combo.IsEnabled = false;
}
var button = o as Button;
if (button != null)
{
button.IsEnabled = false;
}
var textBlock = o as TextBlock;
if (textBlock != null)
{
textBlock.IsEnabled = false;
}
var cb = o as CheckBox;
if (cb != null)
{
cb.IsEnabled = false;
}
var textBox = o as TextBox;
if (textBox == null) return;
textBox.IsEnabled = true;
textBox.IsReadOnly = true;
});
}
public static readonly DependencyProperty ActionOnEachLoadedVisualChildProperty = DependencyProperty.RegisterAttached(
"ActionOnEachLoadedVisualChild", typeof (Action<DependencyObject>), typeof (Attached), new PropertyMetadata(default(Action<DependencyObject>)));
public static void SetActionOnEachLoadedVisualChild(DependencyObject element, Action<DependencyObject> value)
{
element.SetValue(ActionOnEachLoadedVisualChildProperty, value);
}
public static Action<DependencyObject> GetActionOnEachLoadedVisualChild(DependencyObject element)
{
return (Action<DependencyObject>) element.GetValue(ActionOnEachLoadedVisualChildProperty);
}
public static bool GetAreChildrenEnabled(UIElement element)
{
return (bool) element.GetValue(AreChildrenEnabledProperty);
}
public static void SetAreChildrenEnabled(UIElement element, bool value)
{
element.SetValue(AreChildrenEnabledProperty, value);
}
}
帮手代码
public static class VisualTreeHelperExtensions
{
public static T FindParent<T>(this DependencyObject child) where T : DependencyObject
{
while (true)
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
child = parentObject;
}
}
public static List<DependencyObject> GetAllVisualChildren(this DependencyObject parent)
{
var resultedList = new List<DependencyObject>();
var visualQueue = new Queue<DependencyObject>();
visualQueue.Enqueue(parent);
do
{
var depObj = visualQueue.Dequeue();
var childrenCount = VisualTreeHelper.GetChildrenCount(depObj);
for (int i = 0; i < childrenCount; i++)
{
var v = VisualTreeHelper.GetChild(depObj, i);
visualQueue.Enqueue(v);
}
resultedList.Add(depObj);
} while (visualQueue.Count > 0);
resultedList.RemoveAt(0);
return resultedList;
}
}
**简短说明:*
找到您根的所有视觉子项(例如window),扫描它们并根据子项类型执行操作。
此致,
我让它以一种不太优雅的方式工作,遍历所有控件并自己设置 属性。在这样做的同时,我保存了关于我更改了哪些控件以便能够将 UI 重置为原始状态的信息。我对此不是很满意,但它似乎有效。我更喜欢设置和取消设置一些样式,但我没有找到这样做的方法。
这是我最终使用的,但随时 post 更好的东西。首先是禁用部分:
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)
这里是 "reset" 和 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
visited
-set 只是一个局部变量,以避免多次访问控件,这种情况很奇怪,例如对于一些网格。 disabledControls
-set 包含所有未禁用的控件,因此已被代码禁用,并且在 UI 应将其自身重置为原始状态时必须重置。
试试这个,
1.Add 一个布尔值 属性 对用户控件说 CanUserEdit,它控制可以在其他控件中编辑的内容。
2.Add 其他用户控件中的数据触发器并绑定到 CanUserEdit(2 个数据触发器,1 个用于组合框,另一个用于文本框)。
在其中定义没有 key.this 方式的 UserControl 标签,它将影响该用户控件中存在的所有文本框和组合框。
您还将获得集中控制。
示例代码:-
在每个 userControl.
//Replace MainUserControl with your control name
public static readonly DependencyProperty CanUserEditProperty =
DependencyProperty.Register("CanUserEdit", typeof(bool),
typeof(MainUserControl));
public bool CanUserEdit
{
get { return (bool)GetValue(CanUserEditProperty); }
set { SetValue(CanUserEditProperty, value); }
}
在包含文本框和组合框的用户控件中,您可以将以下代码添加到 UserControl.Resources
<UserControl.Resources>
<Style TargetType="TextBox">
<Setter Property="IsReadOnly" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding CanUserEdit}" Value="false">
<Setter Property="IsReadOnly" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="ComboBox">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding CanUserEdit}" Value="false">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
这将影响该控件内的所有组合框和文本框。
并且在您的主窗口中,您将每个 UserControl 的 CanUserEdit 属性 绑定到具有编辑控制权的 UserControl 的 CanUserEdit 属性。
示例(MainUserControl 是具有文本框和组合框的控件):
<local:MainUserControl CanUserEdit="{Binding CanUserEdit,ElementName=CanUserEditControl}" />
现在您只需切换控制编辑的 UserControl 的 CanUserEdit 属性,所有控件都会受到影响。
实现此方案的一种简单方法是通过发布者订阅者实现。将 属性 状态发布到其他用户控件并通过 binding/assigning 将控件状态设置为 属性 到目标控件很容易。 我通过 MvvmLight Messenger 实现了类似的场景,我什至根据一些内部控制状态禁用了一些功能区命令。