问题
I've created a style for a new WPF Window class and have some dependency properties on there. The one to note is
ShowHelpButton
This is supposed to toggle the visibility of the Help button on the window. The code works fine in runtime, but I cannot get it to update the UI in the design view.
Here's the class:
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)));
}
Here's the Style:
<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>
And finally, here's how I'm using it:
<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>
I've seemingly tried everything. I've added all the FrameworkPropertyMetadataOptions by doing this:
FrameworkPropertyMetadataOptions.AffectsArrange |
FrameworkPropertyMetadataOptions.AffectsMeasure |
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure |
FrameworkPropertyMetadataOptions.AffectsParentArrange
I've also added a callback to no avail. I've even tried restarting Visual Studio 2015. I'm starting to think it's just a VS bug, but I'm hoping someone has some idea of what's going on. Thanks for any help!
回答1:
Updated answer
It looks like its a known design-time bug; for subclassed/derived Window objects This reported bug seems to be related to this issue: WPF designer not showing content assigned to custom DependencyProperty
We cannot create a design instance of Window within the designer so we substitute with a proxy type of our own.
So if the designer can't create an instance of derived window type; the binding (TemplateBinding) logic will fail during design-time.
As it is not easy to provide fallback values to TemplateBinding, you can maybe use this approach to provide default values to act as design-time behavior.
回答2:
Sorry I can't recreate your problem.
I go usually in a simpler but still complicated way. I put ViewModel in another assembly, so I would have no temptation to reference it from view. + To make everything stylable, I put Templates into Generic.xaml and override Styles in another dictionary, that is loaded after Generic in App.xaml Here is how I do things.
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>
In App.xaml I remove StartupURI to handle it in 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>
Templates/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>
Themes/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>
I'm not a professional in WPF, but this is what I learned in 1.5 year course of programming a database + wpf interface (nice one).
回答3:
I know this may be a short answer.... But I am thinking the issue, since it is only at design time, might be due to a data context issues in the designer. Have you tried 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
来源:https://stackoverflow.com/questions/43429308/dependency-property-not-updating-visual-studio-designer