bwa*_*all 11 c# wpf xaml user-controls nested-attributes
在工作中,我有几个页面,每个页面都有相同位置的按钮,并具有相同的属性.每个页面也有细微差别.为此,我们创建了一个userControl模板并将所有按钮放入其中,然后将该用户控件应用于所有页面.但是,现在很难访问按钮并从每个页面的xaml修改它们,因为它们位于页面上的UserControl内..... 我如何优雅地访问每个页面的按钮?
我尝试过的:
目前,我们绑定了一堆依赖属性.我不喜欢这个选项,因为我有很多按钮,需要控制这些按钮上的很多属性.结果是数以百计的依赖属性,当我们需要改变某些东西时,它会变得非常混乱.
另一种方法是使用样式.我一般都喜欢这种方法,但由于这些按钮位于另一个控件内部,因此很难对其进行修改,并且模板一次只适用于一个按钮.
Adam Kemp发布了关于让用户在这里插入自己的按钮的消息,这就是我目前正在试图修改/修改的方法.不幸的是,我无法访问Xamarin.
虽然模板的代码运行时插入,模板不正确地更新按钮.如果我在MyButton Setter中放置一个断点,我可以看到该值实际上是一个空按钮,而不是我在主窗口中指定的那个.我该如何解决?
这是一些简化的代码:
我的模板UserControl的xaml:
<UserControl x:Class="TemplateCode.Template"
x:Name="TemplatePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="350"
d:DesignWidth="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Background="DarkGray">
<Grid>
<Button x:Name="_button" Width="200" Height="100" Content="Template Button"/>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
我的模板UserControl的代码背后:
using System.Windows.Controls;
namespace TemplateCode
{
public partial class Template : UserControl
{
public static Button DefaultButton;
public Template()
{
InitializeComponent();
}
public Button MyButton
{
get
{
return _button;
}
set
{
_button = value; //I get here, but value is a blank button?!
// Eventually, I'd like to do something like:
// Foreach (property in value)
// {
// If( value.property != DefaultButton.property) )
// {
// _button.property = value.property;
// }
// }
// This way users only have to update some of the properties
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想用它的应用程序:
<Window x:Class="TemplateCode.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:templateCode="clr-namespace:TemplateCode"
Title="MainWindow"
Height="350"
Width="525"
Background="LimeGreen"
DataContext="{Binding RelativeSource={RelativeSource Self}}" >
<Grid>
<templateCode:Template>
<templateCode:Template.MyButton>
<Button Background="Yellow"
Content="Actual Button"
Width="200"
Height="100"/>
</templateCode:Template.MyButton>
</templateCode:Template>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
现在守则背后:
Using System.Windows;
Namespace TemplateCode
{
Public partial class MainWindow : Window
{
Public MainWindow()
{
InitializeComponent();
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:虽然我想在模板 userControl中删除不必要的依赖项属性,但我还是想在XAML 上设置按钮属性的绑定.
而不是使用许多依赖属性,更喜欢样式方法。样式包含可用于 Button 控件的所有属性。
我将为 UserControl 中的每个按钮样式创建一个 DependencyProperty。
public partial class TemplateUserControl : UserControl
{
public TemplateUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty FirstButtonStyleProperty =
DependencyProperty.Register("FirstButtonStyle", typeof (Style), typeof (TemplateUserControl));
public Style FirstButtonStyle
{
get { return (Style)GetValue(FirstButtonStyleProperty); }
set { SetValue(FirstButtonStyleProperty, value); }
}
public static readonly DependencyProperty SecondButtonStyleProperty =
DependencyProperty.Register("SecondButtonStyle", typeof (Style), typeof (TemplateUserControl));
public Style SecondButtonStyle
{
get { return (Style)GetValue(SecondButtonStyleProperty); }
set { SetValue(SecondButtonStyleProperty, value); }
}
}
Run Code Online (Sandbox Code Playgroud)
然后修改按钮的 xaml 以选择这些样式:
<UserControl x:Class="MyApp.TemplateUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="300"
Background="DarkGray">
<StackPanel>
<Button x:Name="_button" Width="200" Height="100"
Style="{Binding Path=FirstButtonStyle, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
<Button x:Name="_button2" Width="200" Height="100"
Style="{Binding Path=SecondButtonStyle, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</StackPanel>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
现在,当必须自定义按钮时,可以通过自定义样式来实现:
<StackPanel>
<StackPanel.Resources>
<!--common theme properties-->
<Style TargetType="Button" x:Key="TemplateButtonBase">
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="Blue"/>
</Style>
<!--unique settings of the 1st button-->
<!--uses common base style-->
<Style TargetType="Button" x:Key="BFirst" BasedOn="{StaticResource TemplateButtonBase}">
<Setter Property="Content" Value="1st"/>
</Style>
<Style TargetType="Button" x:Key="BSecond" BasedOn="{StaticResource TemplateButtonBase}">
<Setter Property="Content" Value="2nd"/>
</Style>
</StackPanel.Resources>
<myApp:TemplateUserControl FirstButtonStyle="{StaticResource BFirst}"
SecondButtonStyle="{StaticResource BSecond}"/>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
基于@Funk答案的另一个选项是在模板上制作一个内容控件而不是按钮,然后将内容控件的内容绑定到后面代码中的 ButtonProperty :
在模板上:
<ContentControl Content={Binding myButton} Width="200" Height="100"/>
Run Code Online (Sandbox Code Playgroud)
在模板代码后面:
public static readonly DependencyProperty myButtonProperty =
DependencyProperty.Register("Button", typeof(Button), typeof(Template),
new UIPropertyMetadata(new PropertyChangedCallback(ButtonChangedCallback)));
Run Code Online (Sandbox Code Playgroud)
然后在主窗口上:
<Window.Resources>
<Button x:Key="UserButton"
Background="Yellow"
Content="Actual Button"
/>
</Window.Resources>
<Grid>
<templateCode:Template myButton="{StaticResource UserButton}"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
这样做的好处是 Visual Studio 足够智能,可以在设计时显示此代码,并且总体代码较少。
您可以在内容控件上或以默认样式为按钮设置常量(例如位置、字体和颜色),然后仅修改按钮所需的部分。
归档时间: |
|
查看次数: |
1939 次 |
最近记录: |