依赖属性不更新Visual Studio设计器
我已经创建了一个新的WPF Window类的样式,并在那里有一些依赖属性。需要注意的一个是依赖属性不更新Visual Studio设计器
ShowHelpButton
这应该切换窗口上的帮助按钮的可见性。该代码在运行时正常工作,但无法在设计视图中更新UI。
这里的类:
public class MainWindowFrame : Window
{
#region DependencyProperties
public static readonly DependencyProperty ShowHelpButtonProperty = DependencyProperty.Register(
"ShowHelpButton", typeof (bool), typeof (MainWindowFrame), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));
public bool ShowHelpButton
{
get { return (bool) GetValue(ShowHelpButtonProperty); }
set { SetValue(ShowHelpButtonProperty, value); }
}
#endregion
static MainWindowFrame()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MainWindowFrame),
new FrameworkPropertyMetadata(typeof(MainWindowFrame)));
}
这里的风格:
<Style x:Key="MainWindowStyle" TargetType="{x:Type abstractClasses:MainWindowFrame}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="Background" Value="{StaticResource LightBlueBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource BlueBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="1" />
<Setter Property="ResizeMode" Value="NoResize" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="Title" Value="New Window" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type abstractClasses:MainWindowFrame}">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid x:Name="ContainerGrid" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="0"
To="1"
Duration="00:00:01" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid Background="Transparent" MouseDown="Window_MouseDownDrag">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<TextBlock
Margin="10,3,0,3"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Style="{StaticResource CustomTitleBarTextBlackB}"
Text="{TemplateBinding Title}" />
</Grid>
<Button
Grid.Column="1"
Width="20"
Height="20"
Margin="0,0,5,0"
HorizontalAlignment="Right"
AutomationProperties.AutomationId="Help"
Style="{StaticResource HelpButtonStyle}"
Visibility="{TemplateBinding Property=ShowHelpButton,
Converter={StaticResource BoolToVisConverter}}" />
</Grid>
<AdornerDecorator Grid.Row="1">
<ContentPresenter x:Name="WindowContent" />
</AdornerDecorator>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
最后,这里就是我如何使用它:
<abstractClasses:MainWindowFrame
x:Class="Utils.UI.NewFeaturesDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:abstractClasses="clr-namespace:Utils.AbstractClasses"
xmlns:ui="clr-namespace:Utils.UI"
xmlns:utilResx="clr-namespace:Utils.Resources"
Width="775"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
ShowHelpButton="False"
SizeToContent="Height"
Style="{DynamicResource ResourceKey=MainWindowStyle}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Utils;component/WPFStyles/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
</abstractClasses:MainWindowFrame>
我似乎尝试了一切。我已经添加了所有FrameworkPropertyMetadataOptions这样做:
FrameworkPropertyMetadataOptions.AffectsArrange |
FrameworkPropertyMetadataOptions.AffectsMeasure |
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure |
FrameworkPropertyMetadataOptions.AffectsParentArrange
我也添加了一个回调无济于事。我甚至尝试重新启动Visual Studio 2015.我开始认为这只是一个VS错误,但我希望有人对发生了什么有一些想法。谢谢你的帮助!
更新答案
它看起来像它的一个已知的设计时的bug;对于子类/派生窗口对象 该报告的bug,似乎是与此相关的问题:WPF designer not showing content assigned to custom DependencyProperty
我们不能在设计器中创建窗口的设计实例,所以我们有一个代理类型我们自己的替代。
所以如果设计者不能创建派生窗口类型的实例;绑定(TemplateBinding)逻辑将在设计时失败。
因为它是不容易提供后备值TemplateBinding,你也许可以使用这个approach提供的默认值作为设计时行为。
对不起,我不能重新创建你的问题。
我通常以更简单但仍然复杂的方式去。我把ViewModel放在另一个程序集中,所以我没有诱惑从视图中引用它。 +为了使所有样式都可调整,我将模板放入Generic.xaml中,并在另一个字典中重写样式,该样式在App.xaml中的Generic后加载 以下是我如何操作的方法。
MyWindow.xaml:
<Window x:Class="Sandbox.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Sandbox"
xmlns:l="clr-namespace:ProjectLibrary;assembly=ProjectLibrary"
mc:Ignorable="d" d:DataContext="{DynamicResource DesignViewModel}"
Title="MyWindow" Height="300" Width="300">
<Window.Resources>
<l:MyViewModel x:Key="DesignViewModel" SomeButtonVisibility="Collapsed"/>
</Window.Resources>
<StackPanel>
<TextBlock Text="{Binding SomeText}"/>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="1 Button"/>
<Button Visibility="{Binding SomeButtonVisibility}" HorizontalAlignment="Center" VerticalAlignment="Center" Content="2 Button"/>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="3 Button"/>
</StackPanel>
在App.xaml中我删除了的StartupUri来处理它在App.xaml.cs:
using ProjectLibrary;
using System.Windows;
namespace Sandbox {
public partial class App : Application {
MyWindow w;
MyViewModel vm;
public App() {
w = new MyWindow();
//You also can pass Action to open new window of some sort here
//or other things, that VM can't have access to
vm = new MyViewModel(true);
w.DataContext = vm;
w.Show();
}
}
}
MyViewModel:
using System.Windows;
namespace ProjectLibrary
{
public class MyViewModel : Notifiable
{
public MyViewModel() :this(false) {
}
public MyViewModel(bool Execute) {
if (Execute) {
SomeText = "Execution data";
} else {
SomeText = "Design Data";
}
SomeButtonVisibility = Visibility.Visible;
}
private string _someText;
public string SomeText { get { return _someText; } set { _someText = value; RaisePropertyChanged("SomeText"); } }
private Visibility _someButtonVisibility;
public Visibility SomeButtonVisibility { get { return _someButtonVisibility; } set { _someButtonVisibility = value; RaisePropertyChanged("SomeButtonVisibility"); } }
}
}
Notifiable.cs:
using System.ComponentModel;
namespace PTR.PTRLib.Common {
public class Notifiable : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
// take a copy to prevent thread issues
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
的App.xaml:
<Application x:Class="Sandbox.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Sandbox">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Generic.xaml"/> <!-- Default Styles -->
<ResourceDictionary Source="Themes/StyleRes.xaml"/> <!-- ColorTemplates -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
模板/ Generic.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Sandbox">
<Style TargetType="{x:Type local:MyWindow}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ResizeMode" Value="CanResizeWithGrip">
<Setter Property="Template" Value="{StaticResource WindowTemplateKey}"/>
</Trigger>
</Style.Triggers>
</Style>
主题/ StyleRes。XAML:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Sandbox">
<Style TargetType="{x:Type local:MyWindow}">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="LightBlue"/>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="LightBlue"/>
</Style>
我不是在WPF一个专业的,但是这是我在1.5年编程数据库+ WPF界面(好一个)的过程中的经验教训。
噢......至于沙拉达普拉Gururaj说,这是一个已知的bug。现在我记得我曾经处理过类似的事情,但没有找到解决办法。于是,我开始做在用户控件的一切,但现在我意识到,你可以用我的方式很容易做到CustomControls。您可以将每个控件的原型制作为UserControl,然后复制/粘贴并创建一个CustomControl。稍后可以轻松制作模板并重新使用您的控件。 –
感谢您的回复!这可能是一种解决方法,但唯一的问题是所有设计MyWindow的代码都必须在.cs文件中完成,因为我想在包含xaml代码的另一个类中继承MyWindow(不允许你继承在另一个xaml文件中使用xaml定义的类)。我真的不想在cs文件中创建所有的UI代码。 –
我知道这可能是一个简单的答案....但是我想这个问题,因为它只是在设计时,可能是由于在设计数据方面的问题。你有没有尝试d:DataContext?
d:DataContext ="{d:DesignInstance {x:Type nameSpace:ViewModel}, IsDesignTimeCreatable=True}"
https://www.codeproject.com/tips/879109/using-design-time-databinding-while-developing-a-w
尝试在控件模板代替templatebinding使用触发器,看是否有利于 – Liero