Edit:
I'am trying to change Text of TextBox with event trigger, But I am getting a run time error like below.
System.InvalidOperationException: ''(0)' Storyboard.TargetProperty path contains nonanimatable property 'Text'.'
How to change Text with event trigger in WPF
<Style x:Key="mystyle"
TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<StackPanel>
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" />
<ToggleButton HorizontalAlignment="Right"
VerticalAlignment="Top"
Content="search"
Name="searchButton">
<ToggleButton.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames Storyboard.Target="{Binding RelativeSource={RelativeSource AncestorType=TextBox,AncestorLevel=1}}"
Storyboard.TargetProperty="(TextBox.Text)">
<DiscreteStringKeyFrame KeyTime="00:00:00"
Value="texttwo" />
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToggleButton.Triggers>
</ToggleButton>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Edit: since you have totally rewritten the original question, my original answer does not make sense anymore, so I will rewrite it as well.
The problem is that in the EventTrigger you can only use a StoryBoard, and you cannot set the Text property of the TextBox from it. Therefore I think even if it can be achieved purely from WPF with a Template, the solution would be so complicated and ugly that it does not worth it, so I would suggest to create a user control.
If we make a step backward, what is your goal with this customized TextBox?
Edit2:
Finally I could do it with a custom animation class, but I still think that implementing this functionality with a user control is the good solution.
This is the custom animation class (for sake of simplicity I have put it in "local" namespace):
public class TextBoxStringAnimation : StringAnimationBase {
public static readonly DependencyProperty TextBoxToChangeProperty = DependencyProperty.Register(nameof(TextBoxToChange), typeof(TextBox), typeof(TextBoxStringAnimation));
public TextBox TextBoxToChange {
get => (TextBox)this.GetValue(TextBoxToChangeProperty);
set => this.SetValue(TextBoxToChangeProperty, value);
}
public static readonly DependencyProperty NewTextProperty = DependencyProperty.Register(nameof(NewText), typeof(string), typeof(TextBoxStringAnimation));
public string NewText {
get => (string)this.GetValue(NewTextProperty);
set => this.SetValue(NewTextProperty, value);
}
protected override Freezable CreateInstanceCore() => new TextBoxStringAnimation();
protected override string GetCurrentValueCore(string defaultOriginValue, string defaultDestinationValue, AnimationClock animationClock) {
TextBoxToChange.Text = NewText;
return defaultDestinationValue;
}
protected override bool FreezeCore(bool isChecking) {
return true;
}
}
This inherits from StringAnimationBase, and you can set the TextBox and the NewText values directly. I have implemented both as dependency properties, so you can bind them.
When getting the current value (GetCurrentValueCore) it simply sets the Text property of the target TextBox. I had to override FreezeCore, because by default it has returned false, and that causes an InvelidOperationException when the animation is triggered.
So this is an animation that does not animate at all. :) I consider this an ugly solution, but without using a user control I could not come up with a better solution.
Below is the XAML markup. You must set the TargetProperty of the animation, although at the end it is not used - that is why I have specified Tag. If you use the Tag property of the textbox, check if the animation resets it or not.
<Style x:Key="mystyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<StackPanel>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" />
<ToggleButton HorizontalAlignment="Right" VerticalAlignment="Top" Content="search" Name="searchButton">
<ToggleButton.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<local:TextBoxStringAnimation TextBoxToChange="{Binding RelativeSource={RelativeSource AncestorType=TextBox,AncestorLevel=1}}"
NewText="texttwo" Storyboard.TargetProperty="(TextBox.Tag)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToggleButton.Triggers>
</ToggleButton>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Related
I am binding a ListBox to a List in the ViewModel named FilmeSerienListe. SelectedItem is set when ismouseover = True. The SelectedItem of the ListBox is bound to a Property in the ViewModel named SelectedFilmSerie.
This means when the mouse is over a particular ListBoxItem, this ListBoxItem is selected and its value bound to SelectedFilmSerie. BUT this does not seem to work very well, because the SelectedFilmSerie Property is for some reason always NULL. So, I debugged the App to see what did go wrong – Now the weird behaviour – SelectedFilmSerie is in fact NOT the WHOLE time NULL.
At first – when the mouse is over a ListBoxItem – the value parameter is set to the right Object, and it is NOT NULL, BUT then when I go further with my debugging this SelectedFilmSerie Property is recalled and NOW the value parameter is NULL, which make the SelectedFilmSerie Property also NULL.
WPF:
<ListBox ItemsSource="{Binding FilmeSerienListe}"
SelectedItem="{Binding SelectedFilmSerie}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="IsSelected"
Value="true" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
C#
private IEnumerable<FilmeSerien> _filmeSerienListe;
public IEnumerable<FilmeSerien> FilmeSerienListe
{
get => _filmeSerienListe;
set
{
_filmeSerienListe = value;
NotifyPropertyChanged();
}
}
private FilmeSerien _selectedFilmSerie;
public FilmeSerien SelectedFilmSerie
{
get => _selectedFilmSerie;
set
{
Trace.WriteLine(value != null ? "Value is NOT null" : "Value is NULL");
_selectedFilmSerie = value;
NotifyPropertyChanged();
}
}
Debugger:
ismouseover = True:
4xStep Over:
1xStep Over:
4xStep Over:
Output:
The sec the mouse entered the ListBoxItem, I get Value is NOT null and the sec the mouse leaves the ListBoxItem, I get Value is NULL
More details:
The ListBox is a list of cards bound to FilmeSerienListe with the datatype IEnumerable<FilmeSerien> each ListBoxItem is a card which is a representation of a FilmeSerien.
A card contains several Properties that are in a Property with the datatype FilmeSerien. Like: Titel, Img, Vote and other. Vote is an int datatype Property.
Looks something like this:
Problem:
Every Time I hit a star to vote a movie. I get a NullReferenceException because the SelectedFilmSerie is null.
WPF For star:
<Viewbox>
<materialDesign:RatingBar Value="{Binding Vote}"
Orientation="Horizontal"
Foreground="SkyBlue"/>
</Viewbox>
If I understand you correctly, you need to select the ListBox element not by clicking, but by hovering the mouse over it.
To be honest, it does not even occur to my head for what this might be needed.
I asked in the comments to clarify the purpose of such an implementation, but you didn't answer.
But if, I understood your question correctly, then it is implemented like this:
<Window.Resources>
<Style x:Key="listBoxItemStyle" TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid VerticalAlignment="Center" >
<ListBox ItemsSource="{Binding FilmeSerienListe}"
SelectedItem="{Binding SelectedFilmSerie}"
ItemContainerStyle="{DynamicResource listBoxItemStyle}">
</ListBox>
</Grid>
I'm trying to animate buttons to grow when they appear using a style resource. To accomplish this I have used a uniformgrid with 1 row so the buttons will always be the same size and fill the space equally when they are not collapsed. When a button changes their visibility from collapsed to visible I want it to essentially grow to half the container size and the other button to shrink to half the container size (from full size).
Uniformgrid:
<UniformGrid VerticalAlignment="Bottom" Rows="1">
<Button x:Uid="nextBtn" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="backBtn" Content="{loc:Loc Key=STRING_BACK}" Style="{StaticResource NavBtn}" Click="backBtn_Click" Visibility="Collapsed"/>
<Button x:Uid="nextBtn" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="nextBtn" Content="{loc:Loc Key=STRING_NEXT}" Style="{StaticResource NavBtn}" Click="nextBtn_Click"/>
</UniformGrid>
The problem is that I do not want to hardcode either the button or uniformgrid's width. I read that WPF freezes resources, so I unfortunately can't use bindings to help here. Since uniformgrid regulates the size of my buttons, what I essentially want is just to animate my element when its size changes.
Is there any way to do this in WPF, or is there a better approach to this? It seemed possible because while debugging when SizeChanged is called, ActualWidth now has a value while Width is NaN.
Button style:
<Style TargetType="Button" x:Key="NavBtn">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="1"></ScaleTransform>
</Setter.Value>
</Setter>
<Setter x:Uid="Setter_2" Property="Template">
<Setter.Value>
<ControlTemplate x:Uid="ControlTemplate_1" TargetType="{x:Type Button}">
<Border x:Uid="Border_1" Background="{TemplateBinding Background}">
<ContentPresenter x:Uid="ContentPresenter_1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="SizeChanged">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" To="1" Duration="0:00:00.1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
I created a custom Control in a Windows 10 Universal App project, which is containing a Storyboard. The Code of the storyboard is looking like this:
<Storyboard x:Key="StatisticUpdateAnnimation">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(RingSlice.EndAngle)" Storyboard.TargetName="ringSlice">
<EasingDoubleKeyFrame KeyTime="0" Value="45"/>
<EasingDoubleKeyFrame KeyTime="0:0:2.2" Value="{Binding Angle}">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseIn"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
As you can see the x:Key = "StatisticUpdateAnnimation, the storyboard should be triggered only manually in C# code so I do not know how to Play this Storyboard after I created the Custom User Control in the Mainpage file like this:`
local:ProgressRing x:Name="Progress" Margin="7" VerticalAlignment="Top" HorizontalAlignment="Center" Tapped="ProgressRing_Tapped"/>
The style is like this
<Style TargetType="local:RingPresenter" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:RingPresenter">
<Grid>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Mode=TwoWay, ElementName=Representor, Path=EndAngle}" FontFamily="Vladimir Script" FontSize="48"></TextBlock>
<helper:RingSlice InnerRadius="100" Radius="150" StartAngle="0" EndAngle="{TemplateBinding Angle}" Fill="DarkCyan" x:Name="ringSlice">
</helper:RingSlice>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I access my storyboard?
Since I don't know what is your ProgressRing.HelperClasser, here I wrote a sample to show one method using Storyboard inside of the CustomControl. As we know, CustomControl is template control inside of the ResourceDictionary, we can for example use Storyboard inside of the ControlTemplate like this:
Generic.xaml
<Style TargetType="local:ProgressRing">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ProgressRing">
<Grid x:Name="RootGrid">
<Grid.Resources>
<Storyboard x:Key="std">
<ColorAnimation Storyboard.TargetName="brush" Storyboard.TargetProperty="Color"
Duration="0:0:2" From="LightBlue" To="Red" AutoReverse="True" />
</Storyboard>
</Grid.Resources>
<Ellipse Width="100" Height="100">
<Ellipse.Fill>
<SolidColorBrush x:Name="brush" />
</Ellipse.Fill>
</Ellipse>
<TextBlock Text="111" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And in the cs file of this Custom control:
public ProgressRing()
{
this.DefaultStyleKey = typeof(ProgressRing);
this.Loaded += ProgressRing_Loaded;
}
private void ProgressRing_Loaded(object sender, RoutedEventArgs e)
{
StoryboardPlay();
}
public void StoryboardPlay()
{
var rootGrid = this.GetTemplateChild("RootGrid") as Grid;
var std = rootGrid.Resources["std"] as Storyboard;
std.Begin();
}
I played this Storyboard here once it is loaded. Here the Control.GetTemplateChild method is useful, it helps find the named element in the instantiated ControlTemplate visual tree. Then you can get the resource inside this element.
Now if you use this custom control like this:
<local:ProgressRing x:Name="Progress" Margin="7" VerticalAlignment="Top" HorizontalAlignment="Center" Tapped="ProgressRing_Tapped" />
<Button VerticalAlignment="Bottom" Content="Click to play storyboard" Click="Button_Click" />
Now you can get the storyboard to play like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
Progress.StoryboardPlay();
}
I have a question.
I have created a style in WPF designer (XML) for TextBlocks. After IsMouseOver event is fired on any of two image controls, my textBlocks changes its positions. This style is used for some textBlocks.
<Style x:Key="movingTextBlocksStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=image1, Path=IsMouseOver}" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform/>
</Setter.Value>
</Setter>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" From="0" To="-125"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=image2, Path=IsMouseOver}" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform/>
</Setter.Value>
</Setter>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" From="0" To="-125"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
This style will be used as:
<TextBlock x:Name="textBlock1" Style="{StaticResource movingTextBlocksStyle}"/>
<TextBlock x:Name="textBlock2" Style="{StaticResource movingTextBlocksStyle}"/>
My problem is that I want to reuse this style for another textBlocks: textBlock3 and textBlock4 where "Binding ElementName" differs, for example image3 and image4.
I have thought that if there was any possibility to reuse this style with some type of dynamic parameter or argument, it would be great.
I searched for any solution only as xml-code without any C# (I am using C# with WPF) or converter implementation.
Thanks in advance.
Here's pure XAML solution:
Collect all controls on which the text block depends in an array and set it as data context:
<Image x:Name="image1"/>
<Image x:Name="image2"/>
<TextBlock Style="{StaticResource movingTextBlocksStyle}">
<TextBlock.DataContext>
<x:Array Type="system:Object">
<x:Reference>image1</x:Reference>
<x:Reference>image2</x:Reference>
</x:Array>
</TextBlock.DataContext>
</TextBlock>
You'll need to remember to change all bindings on the TextBlock properties accordingly, because data context is no longer inherited. Then in the style definition bind using corresponding array indices:
<DataTrigger Binding="{Binding [0].IsMouseOver}" Value="True">...</DataTrigger>
...
<DataTrigger Binding="{Binding [1].IsMouseOver}" Value="True">...</DataTrigger>
The system: prefix namespace is clr-namespace:System;assembly=mscorlib.
You could define attached properties which would hold the controls on which the TextBox depends, like so (I'll use only one property to keep it brief):
static class Helper
{
public static object GetImage(DependencyObject obj)
{
return (object)obj.GetValue(ImageProperty);
}
public static void SetImage(DependencyObject obj, object value)
{
obj.SetValue(ImageProperty, value);
}
public static readonly DependencyProperty ImageProperty =
DependencyProperty.RegisterAttached(
"Image",
typeof(object),
typeof(Helper),
new PropertyMetadata(null));
}
Then, in the data trigger, bind using the attached property:
...
<DataTrigger Binding="{Binding Path=(local:Helper.Image).IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
...
Lastly, set the property value to be the control on which the TextBlock depends:
<Image x:Name="image1"/>
...
<TextBlock local:Helper.Image="{Binding ElementName=image1}"
Style="{StaticResource movingTextBlocksStyle}"/>
This solution is not pure XAML - it requires a little bit of code-behind to define the attached properties, but I doubt there's an elegant way to completely avoid it.
EDIT: Original title: When I add a custom control based on a timer, my templates are ignored.
I'm working on the 70-511 training kit from Microsoft Press, and combined two practice exercises together from chapter 5.
The problem is that when I add the custom control to my MainWindow, it runs, but the triggers on the Button template are ignored. When the same control is removed, the triggers are honored.
For those who don't have access to the book, and don't feel like analyzing the code, it's a custom control with a label that has a dependency property setup to update on a timer object (once per second) with the current system time.
As you might infer from my attached code, the custom control is in a separate assembly referenced by the 5_3 project.
I'm a bit stumped on this one. What is causing this?
Here is the code:
MainWindow.xaml:
<Window x:Class="chapter5_3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:chapter5_3CustomControl;assembly=chapter5_4CustomControl">
<Window.Resources>
<ControlTemplate TargetType="{x:Type Button}" x:Key="ButtonTemplate">
<Border Name="Bord1" BorderBrush="Olive" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Rectangle Name="rect1">
<Rectangle.Fill>
<SolidColorBrush x:Name="rosyBrush" Color="RosyBrown"/>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Trigger.EnterActions>
<BeginStoryboard Name="bst2">
<Storyboard AutoReverse="False">
<ColorAnimation Duration="0:0:.3"
Storyboard.TargetProperty="Color"
Storyboard.TargetName="rosyBrush" >
<ColorAnimation.By>
<Color A="0" R="100" B="0" G="0"/>
</ColorAnimation.By>
</ColorAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="bst2" />
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Name="bst1">
<Storyboard>
<ThicknessAnimation Storyboard.TargetName="Bord1"
Storyboard.TargetProperty="BorderThickness"
By=".1" Duration="0:0:.3" />
<ColorAnimation AutoReverse="False" To="DarkRed" Duration="0:0:.3"
Storyboard.TargetProperty="Color"
Storyboard.TargetName="rosyBrush" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="bst1" />
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="rect1" Property="Fill" Value="Gray"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Grid>
<Button Template="{StaticResource ResourceKey=ButtonTemplate}" Height="23" Width="100" BorderThickness="2" Name="btnHello" Content="Hello" IsEnabled="False">
</Button>
<ToolBarPanel>
<CheckBox IsChecked="True" Content="Enable Button" Name="cbEnabled" Checked="cbEnabled_Checked" Unchecked="cbEnabled_Checked"/>
</ToolBarPanel>
<my:CustomControl1 Name="customControl11" />
</Grid>
CustomControl1.xaml: (separate assembly)
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:chapter5_3CustomControl">
<Style TargetType="{x:Type local:CustomControl1}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl1}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBlock Foreground="{TemplateBinding Foreground}" HorizontalAlignment="Center"
Text="{Binding Path=Time}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
CustomControl.cs
public class CustomControl1 : Control
{
public static readonly DependencyProperty TimeProperty;
System.Timers.Timer myTimer = new System.Timers.Timer();
delegate void SetterDelegate();
static CustomControl1()
{
FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
TimeProperty = DependencyProperty.Register("Time", typeof(string), typeof(CustomControl1), metadata);
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
}
public CustomControl1()
{
myTimer.Elapsed += timer_elapsed;
myTimer.Interval = 1000;
myTimer.Start();
this.DataContext = this;
}
void TimeSetter()
{
SetValue(TimeProperty, DateTime.Now.ToLongTimeString());
}
void timer_elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Dispatcher.Invoke(new SetterDelegate(TimeSetter),
System.Windows.Threading.DispatcherPriority.Normal);
}
}
Edit:
I wanted to plug a free tool that I use called snoop! You can find it here, and I recommend it as it allows you to inspect your controls at runtime! Snoop Lives here at time of edit: http://snoopwpf.codeplex.com/ It has saved me a lot of time!
Because your Button and CustomControl are in the same row and column of the Grid, your CustomControl is probably covering the Button. You probably just can't see it.
If you set the Background of your CustomControl to say Red, then you will see what area it is covering.
You would need to ensure that the CustomControl doesn't cover the Button, if you want the Button to respond to mouse events. Alternatively, you can set IsHitTestVisible to false on your CustomControl or ensure it's Background is null.