Right, what I have is:
<Window x:Class="WpfGettingThingsDone.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
AllowsTransparency="True"
Background="Transparent"
WindowStyle="None"
Title="{Binding Title}" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary>
<Style x:Key="WindowBorderBackground" TargetType="{x:Type Border}">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
<GradientStop Color="#FF222222" Offset="0" />
<GradientStop Color="#FF222222" Offset="0.2" />
<GradientStop Color="#FFAAAAAA" Offset="0.6" />
<GradientStop Color="#FF222222" Offset="0.7" />
<GradientStop Color="#FFAAAAAA" Offset="0.9" />
<GradientStop Color="#FF222222" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="WindowHeaderedContent" TargetType="{x:Type HeaderedContentControl}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<Border
Background="Black"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="5,5,0,0"
Padding="4"
SnapsToDevicePixels="True"
>
<DockPanel>
<Button DockPanel.Dock="Right" Command="{Binding Path=CloseCommand}">X</Button>
<TextBlock
FontSize="14"
FontWeight="Bold"
Foreground="White"
HorizontalAlignment="Center"
Text="{TemplateBinding Content}" />
</DockPanel>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
<Border CornerRadius="5" Style="{StaticResource WindowBorderBackground}">
<HeaderedContentControl Header="Current Contexts"
Style="{StaticResource WindowHeaderedContent}"
>
</HeaderedContentControl>
</Border>
</Window>
Basically draws a window with a pretty gradient background, using a HeaderedContentControl to create the title bar, which uses a HeaderTemplate to put the x button there.
Like so:
However, as you can see, I've tried binding the command of the X (close) button开发者_StackOverflow中文版 to the CloseCommand in my ViewModel. Assuming my ViewModel is correct and that my lack of understanding of the WPF databinding stuff is the problem, what am I doing wrong? Can it not be done the way I'm trying?
(Note: For the purposes of this question I merged all resources in use by the window into the windows resource dictionary.)
Edit: Since Sam suggested my DataContext for my window isn't set, I'll clarify that it is set, but done in the code behind for App.Xaml when it creates the MainWindow.
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow mainWindow = new MainWindow();
var viewModel = new MainWindowViewModel();
viewModel.RequestClose += (s, ev) => mainWindow.Close();
mainWindow.DataContext = viewModel;
mainWindow.Show();
}
}
Here's another attempt. Your button is in the DataTemplate for the Header of the HeaderedContentControl. This data template has a different data context to the parent control. It's data context is implicitly the value of the Header property. So to fix your problem you would need to do
<HeaderedContentControl Header="{Binding}" .../>
The empty {Binding} statement means "bind the property to the DataContext of this control".
Alternatively, you could use a RelativeSource binding where you set up the Command binding. Something like:
<Button DockPanel.Dock="Right"
Command="{Binding Path=DataContext.CloseCommand, RelativeSource={RelativeSource AncestorType={x:Type HeaderedContentControl}}}">...</Button>
In your Button you specify the Path of the binding, but not the data source. I think what you are missing is setting the DataContext of your window to be the ViewModel. You need something like
<Window ... DataContext="{StaticResource myViewModel}">
...
精彩评论