我正在开发一个通用窗口SDK。
SDK的主要入口点是一个UserControl派生类,它公开了一些功能。
我们不允许我们的用户完全改变外观,这就是我不喜欢CustomControl + generic.xaml +模板部件方法的原因。
但是,我们希望自定义一些子项。就像我们控制的三个不同按钮一样。我想提供合理的默认样式/模板/内容,但我希望我的用户能够完全重新设计这些子项,以防他们想要。或者,只需更改,例如背景颜色,如果他们想这样做。
最好的方法是什么?
Style Button1Style
的曝光(依赖?)属性?ControlTemplate Button1Template
的曝光(依赖?)属性?DataTemplate Button1ContentTemplate
的曝光(依赖?)属性?SDK是可移植的,需要支持Windows 8.1和10,Store和Phones。
更新:我知道数据绑定工作需要依赖项属性。我不知道我的用户是使用数据绑定还是他们不会。 我不需要动画。
我期待的用例如下:
我想让他们在MS Blend中做2-4,只在XAML中。怎么样?
答案 0 :(得分:0)
@Soonts,这里有很多变数。而且,虽然许多StackOverflow书呆子在一个问题中对开发人员提出多个问题的努力得到了解决,但我认为我们可以共同努力以获得答案。
首先,我认为你应该回顾一下我关于这个主题的文章。它着重于用户控件中的双向绑定,这无疑是一种技巧。
http://blog.jerrynixon.com/2013/07/solved-two-way-binding-inside-user.html
其次,我认为理解ControlTemplate绑定,属性动画和绑定以及DataTemplate范围很重要。我在@ Microsoft Virtual Academy的课程中非常深入地讨论了这个主题。
https://mva.microsoft.com/en-us/training-courses/xaml-for-windows-10-controls-14482
对大多数问题的简短回答是依赖属性是您所需要的。由于您使用Windows 8标记了问题,因此利用属性元数据中定义的已更改事件非常重要。同样,这是在文章中。
最后,我写了一个来自用户控制的重要控件,所以我可以确认你想要完成的事情当然是可能的。如果你想查看我的代码,看看我们是否正在做你想要窃取的任何事情,你也可以这样做。
祝你好运。
答案 1 :(得分:0)
实施#1,效果更好。
this
。在用户控件XAML中,包含DefaultStyles资源:
<ResourceDictionary.MergedDictionaries>
<local:DefaultStyles />
</ResourceDictionary.MergedDictionaries>
在用户控件XAML中,引用样式:<Button Style="{Binding MyButtonStyle, TargetNullValue={StaticResource MyButtonDefaultStyle}}" />
其中MyButtonStyle
是在步骤#3中创建的依赖项属性,MyButtonDefaultStyle
是在步骤#1中创建的默认样式
在客户端应用的页面中:
<ResourceDictionary.MergedDictionaries>
<sdk:DefaultStyles />
</ResourceDictionary.MergedDictionaries>
<!-- Debug code: override a single property -->
<Style x:Key="sss" TargetType="Button" BasedOn="{StaticResource MyButtonDefaultStyle}">
<Setter Property="Foreground" Value="Green" />
</Style>
最后,在客户端应用的页面中:
<sdk:TheControl MyButtonStyle={StaticResource sss} />
这样,一切都开箱即用,我的用户可以调整单个边距或颜色而无需复制粘贴XAML页面,或者完全忽略我提供的样式/模板并创建自己的样式/模板。
我想知道有更简单的方法吗?
任务&#34;允许用户部分或全部覆盖样式&#34;并不听起来应该很难完成。
更新:出于某种原因,在Windows Phone 8.1上,您无法设置Content
属性(没有错误,只是没有效果)。幸运的是,您可以设置ContentTemplate
属性,这似乎适用于所有平台。
答案 2 :(得分:0)
啊,你改变了你的问题。你走了。
以下是我过去的做法。
<UserControl>
<Grid Background="{x:Bind MyBackground, FallbackValue=White}">
<TextBlock Text="{x:Bind MyText, FallbackValue=DesigntimeValue }" />
</Grid>
</UserControl>
请注意{x:Bind}不支持设计时值,因此使用FallBackValue基本上会为您提供设计时值。不要将此与您的默认值混淆。
然后这个代码隐藏:
public sealed partial class MyUserControl : UserControl, INotifyPropertyChanged
{
public MyUserControl()
{
InitializeComponent();
}
Brush _MyBackground = new SolidColorBrush(Colors.Blue);
public Brush MyBackground { get { return _MyBackground; } set { Set(ref _MyBackground, value); } }
string _MyText = "Default value";
public string MyText { get { return _MyText; } set { Set(ref _MyText, value); } }
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (!Equals(storage, value))
{
storage = value;
RaisePropertyChanged(propertyName);
}
}
void RaisePropertyChanged([CallerMemberName] string propertyName = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
}
这就是我们在模板10(http://aka.ms/template10)中实施
INotifyPropertyChanged
的方式。你可以随意实现它。
并像这样使用它:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<local:MyUserControl MyBackground="Yellow" MyText="JerryNixon" />
</Grid>
您将在应用的设计时间看到默认值,而不是后备。 FallBackValues将是您在设计用户控件时所看到的。
值得指出的是,您可以使用依赖项属性替换任何这些属性。您想要这样做的唯一原因是,如果您打算将它们设置为动画。
我希望这会有所帮助。祝你好运。