I have a situation where I need to tab using TabKey from one control to another. The condition is that the focus should never go to control that does not have user inputs so only Text, ComboBox, List DatePicker but somehow the focus after 3 controls get the Focus to go to a dashed line Rectangle (Could be of a Grid, StackPanel, I have not been able to findout) around the control groups before it gets into the control. I have searched very thoroughly in Google and stack over flow for a solution but none seem to work.
Various solutions I tried:
1) Here I set FocusVisualStyle property to null right at start up for Grid and StackPanels. Created a new class:
<StackPanel views:FocusVisualTreeChanger.IsChanged="True" Name="parentStackPanel" Orientation="Vertical" Style="{DynamicResource key1}" FocusVisualStyle="{x:Null}">
public class FocusVisualTreeChanger
{
public static bool GetIsChanged(DependencyObject obj)
{
return (bool)obj.GetValue(IsChangedProperty);
}
public static void SetIsChanged(DependencyObject obj, bool value)
{
obj.SetValue(IsChangedProperty, value);
}
public static readonly DependencyProperty IsChangedProperty =
DependencyProperty.RegisterAttached("IsChanged", typeof(bool), typeof(FocusVisualTreeChanger), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits, IsChangedCallback));
private static void IsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (true.Equals(e.NewValue))
{
FrameworkContentElement contentElement = d as FrameworkContentElement;
if (contentElement != null)
{
contentElement.FocusVisualStyle = null;
return;
}
FrameworkElement element = d as FrameworkElement;
if (element != null)
{
element.FocusVisualStyle = null;
}
}
}
}
Did not work.
I tried setting FocusVisualStyle property to null for only Grid and StackPanel seems to go through the codebehind if I put a break point but the focus rectangle does not go away:
<Grid Name="AppointmentGrid" Style="{DynamicResource key2}" FocusVisualStyle="{x:Null}">
Style style = new Style { TargetType = typeof(Grid) };
style.Setters.Add(new Setter(Grid.FocusVisualStyleProperty, null));
style.Setters.Add(new Setter(Grid.FocusableProperty, false));
Application.Current.Resources["key2"] = style;
Application.Current.Resources["key3"] = style;
Application.Current.Resources["key4"] = style;
Style style1 = new Style { TargetType = typeof(StackPanel) };
style1.Setters.Add(new Setter(StackPanel.FocusVisualStyleProperty, null));
style1.Setters.Add(new Setter(StackPanel.FocusableProperty, false));
Application.Current.Resources["key1"] = style1;
Can anyone please help me out with a solution that I have not already tried. None in stackoverflow solutions seem to work. I also set Focusable=false just incase but that doesn't seem to help either.
I also read:
Remove focus rectangle on a UserControl
WPF Control remove focus and hover effect (FocusVisualStyle?!)
WPF: Remove dotted border around focused item in styled listbox
This is what I think I am stuck at. A comment I found in one of the search sites.
That's a great way to change the default value of a DP, but it will not help in situations where a control's style explicitly changes the property value. Unfortunately, FocusVisualStyle is one such property. More specifically, styles for controls like Button, ComboBox, ListBox, etc. tend to explicitly contain a Setter for the FocusVisualStyle property. This setter will override the default value that you establish by overriding the metadata.
Can someone suggest a solution that will work in my case. I have a User control
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:csla="http://schemas.lhotka.net/4.2.0/xaml"
xmlns:input="clr-
FocusVisualStyle="{x:Null}"
Focusable="False"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
mc:Ignorable="d" d:DesignWidth="948"
IsTabStop="False"
TabIndex="-1">
<StackPanel views:FocusVisualTreeChanger.IsChanged="True" Name="parentStackPanel" Orientation="Vertical" Style="{DynamicResource key1}" FocusVisualStyle="{x:Null}"><Grid Name="AppointmentGrid" Style="{DynamicResource key2}" FocusVisualStyle="{x:Null}">
Thanks
Dhiren
Related
I need help with drawing in my combobox. I want to make a combobox of colors for picking. I found some stuff on the internet but none of them is working. So far I have this :
private void MyComb_DrawItem(object sender, DrawItemEventArgs e)
{
Graphics g = e.Graphics;
System.Drawing.Rectangle rect = e.Bounds;
ColorConverter converter = new ColorConverter();
if (e.Index >= 0)
{
string n = ((ComboBox)sender).Items[e.Index].ToString();
System.Drawing.Color c = (System.Drawing.Color)converter.ConvertFromString(n);
SolidBrush b = new SolidBrush(c);
g.FillRectangle(b, rect.X + 110, rect.Y + 5,
rect.Width - 10, rect.Height - 10);
}
}
This is my drawItem method
<Grid>
<ComboBox x:Name="MyComb" HorizontalAlignment="Left" Margin="66,81,0,0" VerticalAlignment="Top" Width="120" />
</Grid>
This is definition of combobox
Type colorType = typeof(System.Drawing.Color);
PropertyInfo[] propInfoList = colorType.GetProperties(BindingFlags.Static |
BindingFlags.DeclaredOnly | BindingFlags.Public);
foreach (PropertyInfo c in propInfoList)
{
MyComb.Items.Add(c.Name);
}
And here I am filling combobox with colors names and then I want to fill to combox with real colors according to the colors names.. But my draw item method is never called. I tried to create some DrawItem handler but, my combobox have no such thing... Then I read something about setting a DrawMode property of combobox, but my combobox doesn't that kind of property at all...
I am using net framework v.4.6.1
Can please anyone tell me, what am I missing ?
Thank you very much
The biggest problem you're having is that you're trying to use code examples that were written for the Winforms API, even though you are using the WPF API. For future reference, you really need to be more careful about identifying the context of tutorials and other resources you find online, to make sure they actually apply to your scenario.
As it happens, we have a number of related questions on Stack Overflow already:
WPF ComboBox as System.Windows.Media.Colors>
WPF - Bind ComboBox Item Foreground to Its Value
Very simple color picker made of combobox
These are all potentially useful to you, but are all based on the answer to this question:
How can I list colors in WPF with XAML?
Which was originally about just displaying the names of colors, and so took a short-cut, using the <ObjectDataProvider/> element in XAML. This led to the need to use a converter in the other questions, to convert either from a string value or a PropertyInfo instance to the appropriate color or brush.
In fact, if your code is already written to use some type of MVVM approach, and especially since you've already written code-behind to retrieve the color values from the Colors type, or at least tried to (one of the problems in your code is that you are using the Winforms Color type instead of the WPF Colors type…again, in Winforms that works fine, but the WPF API follows the Code Analysis/FxCop rules more closely, and the named colors are in the Colors type), it makes sense to just stick with that and provide a direct view model data structure to which you can bind.
In this approach, rather than providing a procedural implementation of the item drawing, you provide in XAML a declarative implementation describing what each item should look like.
Here is an example…
First, some simple view model data structures:
// Very simple container class
class ColorViewModel
{
public Brush Brush { get; }
public string Name { get; }
public ColorViewModel(Brush brush, string name)
{
Brush = brush;
Name = name;
}
}
// Main view model, acts as the data context for the window
class MainViewModel : INotifyPropertyChanged
{
public IReadOnlyList<ColorViewModel> Colors { get; }
private Brush _selectedColor;
public Brush SelectedColor
{
get { return _selectedColor; }
set { _UpdateField(ref _selectedColor, value); }
}
public MainViewModel()
{
Colors = typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.Public)
.Select(p => new ColorViewModel(new SolidColorBrush((Color)p.GetValue(null)), p.Name))
.ToList().AsReadOnly();
}
public event PropertyChangedEventHandler PropertyChanged;
private void _UpdateField<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
With those in hand, the XAML is straight-forward:
<Window x:Class="TestSO47850587ColorComboBox.MainWindow"
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:l="clr-namespace:TestSO47850587ColorComboBox"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<l:MainViewModel/>
</Window.DataContext>
<StackPanel>
<ComboBox Width="100" ItemsSource="{Binding Colors}"
HorizontalAlignment="Left" Grid.IsSharedSizeScope="True"
SelectedValuePath="Brush" SelectedValue="{Binding SelectedColor}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type l:ColorViewModel}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="ComboBoxItem"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Background="{Binding Brush}" HorizontalAlignment="Stretch"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Rectangle HorizontalAlignment="Stretch" Height="24" Fill="{Binding SelectedColor}"/>
</StackPanel>
</Window>
The above displays the color names, using the actual color as the background. If all you really want is a rectangle, then you can replace the <TextBlock/> element with a <Rectangle/> element, binding to its Fill property. Naturally, you can achieve other visual effects, such as a rectangle with a margin. It's just a matter of configuring your data template according to your need.
The main point here is that you should embrace the data binding approach that defines good WPF programming, and that you should definitely not mistake Winforms code examples for WPF. :)
I need to set the font family for the next text to be written in a RichTextBox.
I tried setting that with...
<RichTextBox x:Name="RichTextEditor" MaxWidth="1000" SpellCheck.IsEnabled="True"
FontFamily="{Binding ElementName=TextFontComboBox, Path=SelectedItem}"
FontSize="{Binding ElementName=TextSizeComboBox, Path=SelectedValue}"
Width="Auto" Height="Auto" HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" />
...but it changed the whole text. I suppose that with the Selection property I can restrict the change to be applied just to the selected area. But how for the next -not yet typed- text?
In order to set the FontFamily based on the cursor position you need to define a custom control with a dependency property that helps insert a new Run section by overriding the OnTextInput method.
I included most of the code, you'll need to modify the namespaces to fit your development environment.
The code uses a ViewModel to manage the available fonts and manage if the font changed.
This code is only a prototype and does not deal with focusing issues between the two controls.
To use this code:
1- Type some text in the RichTectBox.
2- Change the font in the ComboBox.
3- Tab back to the RichTextBox.
4- Type some more text.
Here is the custom RichTextBox control:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace RichTextboxFont.Views
{
public class RichTextBoxCustom : RichTextBox
{
public static readonly DependencyProperty CurrentFontFamilyProperty =
DependencyProperty.Register("CurrentFontFamily",
typeof(FontFamily), typeof
(RichTextBoxCustom),
new FrameworkPropertyMetadata(new FontFamily("Tahoma"),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnCurrentFontChanged)));
public FontFamily CurrentFontFamily
{
get
{
return (FontFamily)GetValue(CurrentFontFamilyProperty);
}
set
{
SetValue(CurrentFontFamilyProperty, value);
}
}
private static void OnCurrentFontChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{}
protected override void OnTextInput(TextCompositionEventArgs e)
{
ViewModels.MainViewModel mwvm = this.DataContext as ViewModels.MainViewModel;
if ((mwvm != null) && (mwvm.FontChanged))
{
TextPointer textPointer = this.CaretPosition.GetInsertionPosition(LogicalDirection.Forward);
Run run = new Run(e.Text, textPointer);
run.FontFamily = this.CurrentFontFamily;
this.CaretPosition = run.ElementEnd;
mwvm.FontChanged = false;
}
else
{
base.OnTextInput(e);
}
}
}
}
Here is the XAML:
<Window x:Class="RichTextboxFont.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RichTextboxFont.Views"
xmlns:ViewModels="clr-namespace:RichTextboxFont.ViewModels"
Title="Main Window"
Height="400" Width="800">
<DockPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ComboBox ItemsSource="{Binding Path=Fonts}"
SelectedItem="{Binding Path=SelectedFont, Mode=TwoWay}"/>
<local:RichTextBoxCustom Grid.Row="1"
CurrentFontFamily="{Binding Path=SelectedFont, Mode=TwoWay}"
FontSize="30"/>
</Grid>
</DockPanel>
</Window>
Here is the ViewModel:
If you do not use view models, let me know and I'll add the base class code too; otherwise, google/stackoverflow can help you too.
using System.Collections.ObjectModel;
using System.Windows.Media;
namespace RichTextboxFont.ViewModels
{
public class MainViewModel : ViewModelBase
{
#region Constructor
public MainViewModel()
{
FontFamily f1 = new FontFamily("Georgia");
_fonts.Add(f1);
FontFamily f2 = new FontFamily("Tahoma");
_fonts.Add(f2);
}
private ObservableCollection<FontFamily> _fonts = new ObservableCollection<FontFamily>();
public ObservableCollection<FontFamily> Fonts
{
get
{
return _fonts;
}
set
{
_fonts = value;
OnPropertyChanged("Fonts");
}
}
private FontFamily _selectedFont = new FontFamily("Tahoma");
public FontFamily SelectedFont
{
get
{
return _selectedFont;
}
set
{
_selectedFont = value;
FontChanged = true;
OnPropertyChanged("SelectedFont");
}
}
private bool _fontChanged = false;
public bool FontChanged
{
get
{
return _fontChanged;
}
set
{
_fontChanged = value;
OnPropertyChanged("FontChanged");
}
}
#endregion
}
}
Here is the Window code-behind where I initialise the ViewModel:
using System.Windows;
namespace RichTextboxFont.Views
{
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
this.DataContext = new ViewModels.MainViewModel();
}
}
}
There's a much easier way to do this: Implement a toolbar for your RichTextBox.
Unlike WinForms, the RichTextBox in WPF doesn't come with a toolbar by default, but it's really easy to create one yourself. The RichTextBox automatically handles many EditingCommands, so it's just a matter of creating a toolbar and some buttons. Microsoft has provided sample code for this at the bottom of the RichTextBox Overview on MSDN.
Unfortunately, those editing commands don't include setting the FontFace property of the selection, though you can create a ComboBox on the toolbar that can trigger the change with an event handler in the codebehind file.
That's the approach taken in this CodePlex article by Gregor Pross: WPF RichTextEditor
The project is commented in German, but the source itself is very clearly written. The codebehind used for his font selector ComboBox looks like this:
private void Fonttype_DropDownClosed(object sender, EventArgs e)
{
string fontName = (string)Fonttype.SelectedItem;
if (fontName != null)
{
RichTextControl.Selection.ApplyPropertyValue(System.Windows.Controls.RichTextBox.FontFamilyProperty, fontName);
RichTextControl.Focus();
}
}
The main reason that people struggle with the FontFace selection is that after the font selection has been made, you must return focus to the RichTextBox. If the user must manually press tab or click into the RichTextBox, a new text selection gets created and you lose the formatting options you've chosen.
One of the answers to this StackOverflow question discusses that problem.
WPF Richtextbox FontFace/FontSize
This isn't exactly a trivial answer.
To do inline text formatting in a Rich TextBox like you want you will have to modify the Document property of the RichTextBox. Very simply, something like this will work
<RichTextBox >
<RichTextBox.Document>
<FlowDocument>
<Paragraph>
<Run>Something</Run>
<Run FontWeight="Bold">Something Else</Run>
</Paragraph>
</FlowDocument>
</RichTextBox.Document>
</RichTextBox>
I think you could create a custom Control that creates a new block element and sets the font properties you need based on the user input.
For example, If the user types something then presses bold. You would want to wrap the previous text in a run and create a new run element setting the FontWeight to bold then the subsequent text will be wrapped in the bolded run.
Again, not a trivial solution but I can't think of any other way to accomplish what you are after.
I have to iterate through all children of a stackPanel.
Being new to WPF I do that
foreach (var item in spTab3.Children)
{
if (item.GetType() == typeof(ListBox))
((ListBox)item).Visibility = Visibility.Collapsed;
if (item.GetType() == typeof(Grid))
((Grid)item).Visibility = Visibility.Collapsed;
....
}
that is I have to cast all types of elements to get to set the visibility. I bet there is a smarter way to do all the togheter.
Thanks
---EDIT---
So in short I have a stackpanel spTab3 with children.
When I do what suggested by Bijington:
spTab3.Visibility = Visibility.Collapsed;<----------set all children to collapsed
spTab3.Children[iVisibleTab-1].Visibility = Visibility.Visible;<----set only one to visible
the second line has no effect.
While when I do as stated by Spawn that works:
foreach (var item in spTab3.Children)
((UIElement)item).Visibility = Visibility.Collapsed;
spTab3.Children[iVisibleTab-1].Visibility = Visibility.Visible;
can anyone explain me why?!?
Every child in Panel is UIElement. So its type derived from DependencyObject which has SetValue method. Use it.
foreach (UIElement item in spTab3.Children)
{
item.SetValue(UIElement.VisibilityProperty, Visibility.Collapsed (or Visible));
}
Keep in mind that it's not a WPF style solution. You better need to declare dependency property and to bind item's visibility to this property.
In case that panel and code are inside a Window
public static readonly DependencyProperty IsItemVisibleProperty = DependencyProperty.Register("IsItemVisible", typeof(Visibility), typeof(MainWindow), new FrameworkPropertyMetadata(Visibility.Visible));
public Visibility IsItemVisible
{
get
{
return (Visibility)GetValue(IsItemVisibleProperty);
}
set
{
SetValue(IsItemVisibleProperty, value);
}
}
XAML:
<Window x:Class="WpfApplication1.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">
<StackPanel>
<Button Visibility="{Binding IsItemVisible,RelativeSource={RelativeSource AncestorType=Window}}">Collapsed 1</Button>
<Button Visibility="{Binding IsItemVisible,RelativeSource={RelativeSource AncestorType=Window}}">Collapsed 2</Button>
<Button>Visible</Button>
</StackPanel>
</Window>
A more efficient way of showing/hiding the Children within the StackPanel would be to simply set the Visibility property on the StackPanel itself.
My DataGrid is bound to a data source, which is a database. When user right clicks somewhere over the DataGrid control, I'd like to be able to recognize over which column he or she did it. Scenario is as follows - if ContextMenu is opened over a column holding dates, then (for example) I would like to present him with options to filter out dates smaller, greater or equal to the date selected.
<DataGrid.Resources>
<Helpers:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>
<DataGrid.ContextMenu>
<ContextMenu DataContext="{Binding Path=DataContext}">
<MenuItem Header="Cokolwiek" Command="{Binding Source={StaticResource proxy}, Path=Data.FK}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent.PlacementTarget.DataContext}"/>
</ContextMenu>
</DataGrid.ContextMenu>
PlacementTarget is a reference to the DataGrid, and I'd like it to be a reference to DataGridColumn.
BindingProxy class:
public class BindingProxy : Freezable {
protected override Freezable CreateInstanceCore() {
return new BindingProxy();
}
public object Data {
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Data.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object),
typeof(BindingProxy), new UIPropertyMetadata(null));
}
What you can do is hook up to the PreviewMouseUp event so you can look at the Source property of the Event that is raised.
With the exception of direct events, WPF defines most routed events in pairs - one tunnelling and the other bubbling. The tunnelling event name always begins with 'Preview' and is raised first. This gives parents the chance to see the event before it reaches the child. This is followed by the bubbling counterpart. In most cases, you will handle only the bubbling one. The Preview would be usually used to
block the event (e.Handled = true) cause the parent to do something in
advance to normal event handling.
e.g. if UI Tree = Button contains Grid contains Canvas contains Ellipse
Clicking on the ellipse would result in (MouseDownButton is eaten up by Button and Click is raised instead.)
private void OnPreviewMouseUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
var source = mouseButtonEventArgs.Source;
// Assuming the DataGridColumn's Template is just a TextBlock
// but depending on the Template which for sure should at least inherit from FrameworkElement to have the Parent property.
var textBlock = source as TextBlock;
// Not a good check to know if it is a holding dates but it should give you the idea on what to do
if (textBlock != null)
{
var dataGridColumn = textBlock.Parent as DataGridColumn;
if (dataGridColumn != null)
{
if ((string) dataGridColumn.Header == "Holding Dates")
{
// Show context menu for holding dates
}
}
}
// Other stuff
else if (somethingElse)
{
// Show context menu for other stuff
}
}
To put it simply, I have this within a ControlTemplate.Triggers condition EnterAction:
<ColorAnimation To="#fe7" Storyboard.TargetProperty="Background.Color" Duration="00:00:00.1" Storyboard.TargetName="brd"/>
But I want the 'to' colour (#fe7) to be customisable. This is a control derived from ListBox. I can create a DependencyProperty, but of course, I cannot bind the To property of the ColorAnimation to it because the Storyboard has to be frozen and you can't freeze something with bindings (as I understand it).
I tried using a {StaticResource} within the To, then populating the resource in the code-behind when the DependencyProperty was changed, by setting this.Resources["ItemColour"] = newValue; for instance. That didn't work perhaps obviously, it's a static resource after all: no new property values were picked up. DynamicResource gave the same problem relating to inability to freeze.
The property is only set once when the control is created, I don't have to worry about it changing mid-animation.
Is there a nice way of doing this? Do I have to resort to looking for property changes myself, dynamically invoking and managing storyboards at that point? Or overlaying two versions of the control, start and end colour, and animating Opacity instead? Both seem ludicrous..
Kieren,
Will this serve your purpose?
I have extended the Grid class called CustomGrid and created a TestProperty whose value when changed will change the background color of Grid:
public class CustomGrid : Grid
{
public bool Test
{
get
{
return (bool)GetValue(TestProperty);
}
set
{
SetValue(TestProperty, value);
}
}
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test", typeof(bool), typeof(CustomGrid),
new PropertyMetadata(new PropertyChangedCallback
((obj, propChanged) =>
{
CustomGrid control = obj as CustomGrid;
if (control != null)
{
Storyboard sb = new Storyboard() { Duration = new Duration(TimeSpan.FromMilliseconds(500)) };
Random rand = new Random();
Color col = new Color()
{
A = 100,
R = (byte)(rand.Next() % 255),
G = (byte)(rand.Next() % 255),
B = (byte)(rand.Next() % 255)
};
ColorAnimation colAnim = new ColorAnimation();
colAnim.To = col;
colAnim.Duration = new Duration(TimeSpan.FromMilliseconds(500));
sb.Children.Add(colAnim);
Storyboard.SetTarget(colAnim, control);
Storyboard.SetTargetProperty(colAnim, new PropertyPath("(Panel.Background).(SolidColorBrush.Color)"));
sb.Begin();
}
}
)));
}
This is the button click event that changes the color:
private void btnClick_Click(object sender, RoutedEventArgs e)
{
gridCustom.Test = (gridCustom.Test == true) ? false : true;
}
I am changing the background color of Grid because I don't have your Listbox.
Finally this is the xaml:
<Grid x:Name="grid" Background="White">
<local:CustomGrid x:Name="gridCustom" Background="Pink" Height="100" Margin="104,109,112,102" >
</local:CustomGrid>
<Button Content="Click Me" x:Name="btnClick" Height="45" HorizontalAlignment="Left" Margin="104,12,0,0" VerticalAlignment="Top" Width="145" Click="btnClick_Click" />
</Grid>
Will this serve your purpose? Let me know or I misunderstood the question?
EDIT:
See this code:
ColorAnimation's To property cannot be bound as you probably guessed. But that doesn't mean you can't change it's value. You can always get a reference to the ColorAnimation and change it's To value and it will all work out well. So from WPF world of binding we need to change a bit and bind the data how we used to do it in Winforms :). As an example see this:
This is the xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="ControlTemplateTriggers.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Storyboard x:Key="Storyboard">
<ColorAnimation From="Black" To="Red" Duration="00:00:00.500" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="gridCustom" />
</Storyboard>
</Window.Resources>
<Grid x:Name="grid" Background="White">
<Grid x:Name="gridCustom" Background="Pink" Height="100" Margin="104,109,112,102" />
<Button Content="Click Me" x:Name="btnClick" Height="45" HorizontalAlignment="Left" Margin="104,12,0,0" VerticalAlignment="Top" Width="145" Click="btnClick_Click" />
</Grid>
</Window>
This is the code behind:
using System.Windows;
using System.Windows.Media.Animation;
using System.Windows.Media;
using System;
namespace Sample {
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void btnClick_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = this.Resources["Storyboard"] as Storyboard;
if (sb != null)
{
ColorAnimation frame = sb.Children[0] as ColorAnimation;
Random rand = new Random();
Color col = new Color()
{
A = 100,
R = (byte)(rand.Next() % 255),
G = (byte)(rand.Next() % 255),
B = (byte)(rand.Next() % 255)
};
frame.To = col;
sb.Begin();
}
}
}
}
As you can see I am getting a reference to the storyboard and changing it's To property. Your approach to StaticResource obviously wouldn't work. Now what you can do is, in your DependencyProperty callback somehow get a reference to the Timeline that you want to animate and using VisualTreeHelper or something and then set it's To property.
This is your best bet.
Let me know if this solved your issue :)
can u put multiple DataTriggers with each having respective color for the "To" property...
Surely not..
What i understood is that u want color A on the Condition A and Color B on some other condition B....so if there's a property with multiple options u can put datatriggers for those condition only...like if Job done = Red, Half done = Green like wise..
If i misunderstood the problem please correct me..
I think i got ur question ...UR control is user configurable so what ever user select , control's background needs to be set to that color with animation right?
It turns out this is simply not possible.