Damn, this was a tricky one – a bit of coding, a sprinkle of XAML and here it is. And it works. You can set this Behavior to any TextBox and turn it into Windows 7 search box like thingy. You can define your own Search and Clear icons (ImageSource) and (if you don’t want search-as-you-type) Search command (ICommand). The good thing is that it doesn’t affect the style/template you set for the TextBox, as it is implemented as Adorner.
Download here (rename .DOC to .RAR – wordpress limitation).
Another behavior that I wrote for my project. The code is simple and there aren’t many things to configure, but it is a good starting point for a nice button popup (many other examples I’ve seen are coded as custom controls; the same can be accomplished using this behavior):
If you ever happen to stumble upon a problem of having the need to support multiple versions of the same assembly in your .NET project, read on… Take these two assemblies for example:
Foo.dll (v1.0)
namespace Foo
{
class Bar
{
public void Do()
{
Console.WriteLine("Hello, from v1.0 of Bar");
}
}
}
Foo.dll (v2.0)
namespace Foo
{
class Bar
{
public void Do(string parameter)
{
Console.WriteLine("Hello, from v2.0 of Bar with parameter: {0}", parameter);
}
}
}
So, now we have two Foo.dll assemblies that are of different version and we want to use them in our project. First, copy these assemblies to project directory and put them under v1 and v2 directories (at the same level as the .csproj file); then, open the .csproj file and add the following configurations (I’ll do this for DEBUG versions – just copy DEBUG that is already there and modify it; the RELEASE is similar):
Ever since I wrote Animated Height Behavior, I wanted to create Behavior that will give me nice eye-candy for all my IDataErrorInfo validation needs. You can see the result in the video below, as well as the code of the Behavior. Please note that the image I’m using here is from the Resources (just add 16×16 png image to Resources and name it Error16). GetBitmapSource() is Extension that I wrote for converting System.Drawing.Bitmap to BitmapSource.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace Foo
{
public class AnimatedErrorInfoBehavior : Behavior<FrameworkElement>
{
private readonly TextBlock textBlock_;
private Grid errorGrid_;
private readonly DoubleAnimation increaseHeightAnimation_;
private readonly Storyboard increaseHeightStoryboard_;
private readonly DoubleAnimation showAnimation_;
private readonly Storyboard showStoryboard_;
private readonly DoubleAnimation decreaseHeightAnimation_;
private readonly Storyboard descreaseHeightStoryboard_;
private readonly DoubleAnimation hideAnimation_;
private readonly Storyboard hideStoryboard_;
private readonly Dictionary<string, int> errors_;
public AnimatedErrorInfoBehavior()
{
errors_ = new Dictionary<string, int>();
textBlock_ = new TextBlock();
increaseHeightAnimation_ = new DoubleAnimation(
0.0,
23.0,
TimeSpan.FromMilliseconds(200)
);
increaseHeightAnimation_.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
increaseHeightStoryboard_ = new Storyboard();
Storyboard.SetTarget(increaseHeightAnimation_, errorGrid_);
Storyboard.SetTargetProperty(increaseHeightAnimation_, new PropertyPath(FrameworkElement.HeightProperty));
increaseHeightStoryboard_.Children.Add(increaseHeightAnimation_);
showAnimation_ = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(200));
showAnimation_.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseIn };
showStoryboard_ = new Storyboard();
Storyboard.SetTarget(showAnimation_, textBlock_);
Storyboard.SetTargetProperty(showAnimation_, new PropertyPath(UIElement.OpacityProperty));
showStoryboard_.Children.Add(showAnimation_);
decreaseHeightAnimation_ = new DoubleAnimation(
23.0,
0.0,
TimeSpan.FromMilliseconds(100)
);
descreaseHeightStoryboard_ = new Storyboard();
Storyboard.SetTarget(decreaseHeightAnimation_, errorGrid_);
Storyboard.SetTargetProperty(decreaseHeightAnimation_, new PropertyPath(FrameworkElement.HeightProperty));
descreaseHeightStoryboard_.Children.Add(decreaseHeightAnimation_);
hideAnimation_ = new DoubleAnimation(1.0, 0.0, TimeSpan.FromMilliseconds(100));
hideAnimation_.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
hideStoryboard_ = new Storyboard();
Storyboard.SetTarget(hideAnimation_, textBlock_);
Storyboard.SetTargetProperty(hideAnimation_, new PropertyPath(UIElement.OpacityProperty));
hideStoryboard_.Children.Add(hideAnimation_);
}
protected override void OnAttached()
{
var parent = VisualTreeHelper.GetParent(AssociatedObject) as Grid;
if (parent == null)
return;
var row_index = Grid.GetRow(AssociatedObject);
var row_span = Grid.GetRowSpan(AssociatedObject);
var column_index = Grid.GetColumn(AssociatedObject);
var column_span = Grid.GetColumnSpan(AssociatedObject);
parent.Children.Remove(AssociatedObject);
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
Grid.SetRow(grid, row_index);
Grid.SetRowSpan(grid, row_span);
Grid.SetColumn(grid, column_index);
Grid.SetColumnSpan(grid, column_span);
grid.Children.Add(AssociatedObject);
Grid.SetRow(AssociatedObject, 0);
errorGrid_ = new Grid();
errorGrid_.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
errorGrid_.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
errorGrid_.Height = 0;
var image = new Image();
image.Source = Resources.Error16.GetBitmapSource();
image.Margin = new Thickness(0,0,2,7);
errorGrid_.Children.Add(image);
Grid.SetColumn(image, 0);
textBlock_.Foreground = Brushes.Red;
errorGrid_.Children.Add(textBlock_);
Grid.SetColumn(textBlock_, 1);
grid.Children.Add(errorGrid_);
Grid.SetRow(errorGrid_, 1);
parent.Children.Add(grid);
Validation.AddErrorHandler(AssociatedObject, OnError);
Validation.SetErrorTemplate(AssociatedObject, null);
base.OnAttached();
}
private void OnError(object sender, ValidationErrorEventArgs e)
{
var error_msg = e.Error.ErrorContent.ToString();
if (e.Action == ValidationErrorEventAction.Added)
{
if (errors_.ContainsKey(error_msg))
errors_[error_msg]++;
else
errors_.Add(error_msg, 1);
if (errors_[error_msg] == 1)
{
textBlock_.Text = e.Error.ErrorContent.ToString();
increaseHeightStoryboard_.Begin(errorGrid_);
showStoryboard_.Begin(textBlock_);
}
}
if (e.Action == ValidationErrorEventAction.Removed)
{
errors_[error_msg]--;
if (errors_[error_msg] == 0)
{
descreaseHeightStoryboard_.Begin(errorGrid_);
hideStoryboard_.Begin(textBlock_);
}
}
}
}
}
If you are like me, you probably keep bitmaps (png files) of your WPF project in Resources. Since Resources uses System.Drawing.Bitmap for storing bitmaps, I wrote (some code modifications were done by Bojan) this little extension that will convert bitmap resource to BitmapSource.
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Foo
{
public static class BitmapExtension
{
public static BitmapSource GetBitmapSource(this Bitmap image)
{
var rect = new Rectangle(0, 0, image.Width, image.Height);
var bitmap_data = image.LockBits(rect, ImageLockMode.ReadOnly, image.PixelFormat);
try
{
BitmapPalette palette = null;
if (image.Palette.Entries.Length > 0)
{
var palette_colors = image.Palette.Entries.Select(entry => System.Windows.Media.Color.FromArgb(entry.A, entry.R, entry.G, entry.B)).ToList();
palette = new BitmapPalette(palette_colors);
}
return BitmapSource.Create(
image.Width,
image.Height,
image.HorizontalResolution,
image.VerticalResolution,
ConvertPixelFormat(image.PixelFormat),
palette,
bitmap_data.Scan0,
bitmap_data.Stride * image.Height,
bitmap_data.Stride
);
}
finally
{
image.UnlockBits(bitmap_data);
}
}
private static System.Windows.Media.PixelFormat ConvertPixelFormat(System.Drawing.Imaging.PixelFormat sourceFormat)
{
switch (sourceFormat)
{
case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
return PixelFormats.Bgr24;
case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
return PixelFormats.Bgra32;
case System.Drawing.Imaging.PixelFormat.Format32bppRgb:
return PixelFormats.Bgr32;
}
return new System.Windows.Media.PixelFormat();
}
}
}
On one project that I’m working on, I had a need to animate height (simulating Visible/Not Visible state of ‘overlay’ and edit dialogs) of FrameworkElement. So I wrote this little behavior that does just that. You can use IsVisible to control (using binding) ‘Visibility’, as well as ShowDuration and HideDuration to control duration of animation.
using System;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Media.Animation;
namespace Foo
{
public class AnimatedHeightBehavior : Behavior<FrameworkElement>
{
private static DoubleAnimation showAnimation_;
private static readonly Storyboard showStoryboard_ = new Storyboard();
private static DoubleAnimation hideAnimation_;
private static readonly Storyboard hideStoryboard_ = new Storyboard();
public static DependencyProperty IsVisibleProperty =
DependencyProperty.Register(
"IsVisible",
typeof(bool),
typeof(AnimatedHeightBehavior),
new PropertyMetadata(false, OnShowChanged)
);
public static DependencyProperty ShowDurationProperty =
DependencyProperty.Register(
"ShowDuration",
typeof(int),
typeof(AnimatedHeightBehavior),
new PropertyMetadata(200)
);
public static DependencyProperty HideDurationProperty =
DependencyProperty.Register(
"HideDuration",
typeof(int),
typeof(AnimatedHeightBehavior),
new PropertyMetadata(50)
);
public bool IsVisible
{
get { return (bool)GetValue(IsVisibleProperty); }
set { SetValue(IsVisibleProperty, value); }
}
public int ShowDuration
{
get { return (int)GetValue(HideDurationProperty); }
set { SetValue(HideDurationProperty, value); }
}
public int HideDuration
{
get { return (int)GetValue(ShowDurationProperty); }
set { SetValue(ShowDurationProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnLoaded;
}
protected override void OnDetaching()
{
AssociatedObject.Loaded -= OnLoaded;
base.OnDetaching();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (!IsVisible)
AssociatedObject.Height = 0.0;
showAnimation_ = new DoubleAnimation(
0.0,
AssociatedObject.ActualHeight,
TimeSpan.FromMilliseconds((int)GetValue(ShowDurationProperty))
);
showAnimation_.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
Storyboard.SetTarget(showAnimation_, AssociatedObject);
Storyboard.SetTargetProperty(showAnimation_, new PropertyPath(FrameworkElement.HeightProperty));
showStoryboard_.Children.Add(showAnimation_);
hideAnimation_ = new DoubleAnimation(
AssociatedObject.ActualHeight,
0.0,
TimeSpan.FromMilliseconds((int)GetValue(HideDurationProperty))
);
Storyboard.SetTarget(hideAnimation_, AssociatedObject);
Storyboard.SetTargetProperty(hideAnimation_, new PropertyPath(FrameworkElement.HeightProperty));
hideStoryboard_.Children.Add(hideAnimation_);
}
private static void OnShowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = ((AnimatedHeightBehavior)d).AssociatedObject;
if ((bool)e.NewValue)
showStoryboard_.Begin(element);
else
hideStoryboard_.Begin(element);
}
}
}
TextBox style that you can use in WPF 3.5 and WPF 4. Do note that the provided Resource Dicitionary has SelectedBrush defined which must be removed if you intend to use this style in WPF 3.5 (WPF 4 only property).
Download here (rename .DOC to .RAR – wordpress limitation).
Here are some button styles I’ve been working on for one of my personal projects. Styles are compatible with both WPF 3.5 and WPF 4 – I used only triggers. There are blue, green and red styles, as you can see in the screenshot below:
Download here (rename .DOC to .RAR – wordpress limitation).
This is one of those problems that I couldn’t solve for so long… I’m posting a small code example of how it can be done without the need for user interaction – great for batch type of Addin. In the following example, adoc is AcadDocument, path is absolute path to where you want your DWF to be published.
Dim dsd_path = path + ".dsd"
Dim dwf_path = path + ".dwf"
Dim dsd_stream = File.Open(dsd_path, FileMode.Create)
Dim dsd_writer As New StreamWriter(dsd_stream)
dsd_writer.WriteLine("[DWF6Version]")
dsd_writer.WriteLine("Ver=1")
For Each layout As Object In adoc.Layouts
Dim sheet_line As String = "[DWF6Sheet:" + layout.Name + "]"
dsd_writer.WriteLine(sheet_line)
Dim dwg_line As String = "DWG=" + adoc.Path
dsd_writer.WriteLine(dwg_line)
Dim layout_line As String = "Layout=" + layout.Name
dsd_writer.WriteLine(layout_line)
Next
dsd_writer.WriteLine("[Target]")
dsd_writer.WriteLine("Type=1")
Dim dwf_line As String = "DWF=" + dwf_path
dsd_writer.WriteLine(dwf_line)
dsd_writer.WriteLine("PWD=")
dsd_writer.Close()
Dim dsd_data As New DsdData()
dsd_data.ReadDsd(dsd_path)
dsd_data.ProjectPath = Path.GetDirectoryName(path)
dsd_data.LogFilePath = path + ".log"
dsd_data.NoOfCopies = 1
dsd_data.SheetType = SheetType.MultiDwf
dsd_data.SheetSetName = "PublisherSet"
dsd_data.WriteDsd(dsd_path)
Dim reader As New StreamReader(dsd_path)
Dim content = reader.ReadToEnd()
reader.Close()
content = content.Replace("PromptForDwfName=TRUE", "PromptForDwfName=FALSE")
Dim writer As New StreamWriter(dsd_path)
writer.Write(content)
writer.Close()
Dim final_dsd As New DsdData()
final_dsd.ReadDsd(dsd_path)
Dim plot_cfg As PlotConfig
For Each cfg_info As PlotConfigManager.Devices
If cfg_info.DeviceName.Contains("DWF") Then
plot_cfg = PlotConfigManager.SetCurrentConfig(cfg_info.DeviceName)
Exit For
End If
Next
Dim publisher = Application.Publisher
publisher.PublishExecute(final_dsd, plot_cfg)