I am attempting to implement a ColorAnimation on the Fill of an Ellipse, but not having any success. (I am implementing this ColorAnimation in the code-behind of my app's MainWindow, called via the Messenger pattern from the View Model.):
public partial class MainWindow : Window
{
private SolidColorBrush fillBrush = new SolidColorBrush(Colors.Red);
private ColorAnimation ca = new ColorAnimation(Colors.Red, Colors.Yellow, new Duration(TimeSpan.FromMilliseconds(800)));
private Storyboard flashEllipse = new Storyboard();
public MainWindow(MainWindowVM viewModel)
{
DataContext = viewModel;
InitializeComponent();
Messenger.Default.Register<string>(this, StartFlashEllipse, Constants.StartMsg);
Messenger.Default.Register<string>(this, StopFlashEllipse, Constants.StopMsg);
RegisterName("EllipseFillBrush", fillBrush);
Storyboard.SetTargetName(ca, "EllipseFillBrush");
Storyboard.SetTargetProperty(ca, new PropertyPath("(0).(1)", Ellipse.FillProperty, SolidColorBrush.ColorProperty));
flashEllipse.Children.Add(ca);
flashEllipse.RepeatBehavior = RepeatBehavior.Forever;
}
private void StartFlashEllipse(string ellipseTag)
{
Dispatcher.Invoke(DispatcherPriority.Render, (Action)delegate ()
{
Ellipse ellipseToFlash = <code to find Ellipse in Window>;
ellipseToFlash.Fill = new SolidColorBrush(Colors.Blue);
flashEllipse.Begin(ellipseToFlash);
});
}
...
}
I got the PropertyPath code from this StackOverflow question, but I am still getting a similar Exception on the flashEllipse.Begin() line as the OP of this question:
''Fill' property does not point to a DependencyObject in path '(0).(1)'.'
What am I missing here?
You do not need a Storyboard and a complex PropertyPath.
Just directly start an animation of the Color property of the SolidColorBrush:
ellipseToFlash.Fill = new SolidColorBrush(Colors.Blue);
ellipseToFlash.Fill.BeginAnimation(SolidColorBrush.ColorProperty, ca);
Related
Sorry for the stupid question but I can't get it to work.
I got a MainWindow that opens another window.
public static Window2 LoadWindow = new Window2();
public MainWindow()
{
InitializeComponent();
LoadWindow.Show();
Later in the code, I Start a function that creates a Background worker in the new window
if (MainWindow.Start == true)
{
MainWindow.LoadWindow.LoadImage(null, null);
MainWindow.Start = false;
}
public void LoadImage(object sender, RoutedEventArgs e)
{
worker = new BackgroundWorker();
...
And then I tried this to Change the Visibility of the MainWindow.
private void worker_Completed(object sender, RunWorkerCompletedEventArgs e)
{
Application.Current.Dispatcher.Invoke(new Action(() => {
Application.Current.MainWindow.Visibility = Visibility.Visible;
}));
}
I thought Application.Current.MainWindow would point to my MainWindow but the debugger said that Window2 is the Current.MainWindow.
Actually, I am completely confused about the MainWindow.
Typically I initialize a class with a name and use it with that name. (e.g. Window2=class, LoadWindow=it's name)
But what is the name of the MainWindow or how can I interact with it from another window. It's so confusing when the MainWindow != the MainWindow >.<.
You could either inject LoadWindow with a reference to the MainWindow when you create it in the constructor, or you could get a reference to the MainWindow using the Application.Current.Windows collection:
var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (mainWindow != null)
mainWindow.Visibility = Visibility.Visible;
In certain cases I have the problem that the FontSize that I set on a WPF window is not inherited to a child control.
It happens, if a custom user control sets its content (e.g. a Label) upon changing the DataContext.
I can reproduce this when putting this UserControl into a new window, then close this window and create a new one having the same UserControl in it (see the following code).
In my complex application it's a custom popup window and a custom UserControl that changes its content if the DataContext is changed. There the font is not inherited upon the first open of the window (so the usercontrol hasn't been in another visual/logical tree until that) but I can't reproduce this in a small test application.
public partial class App : Application
{
// App.xaml: ShutdownMode="OnExplicitShutdown"
private void Application_Startup(object sender, StartupEventArgs e)
{
var testControl = new TestControl();
var w = new Window();
w.FontSize = 40;
w.DataContext = this;
w.Content = testControl; // TestControl.DataContextChanged creates label which has FontSize = 40
w.Show();
w.Close();
w.DataContext = null;
//w.Content = null; // if this is done, the font will be correct (40)
w = null;
w = new Window();
w.FontSize = 40;
w.DataContext = this;
//testControl.DataContext = this; // if this is done, the font will be correct (40)
w.Content = testControl; // TestControl.DataContextChanged creates label with remaining FontSize = 12 (Default)
w.Show();
}
}
public class TestControl : UserControl
{
public TestControl()
{
DataContextChanged += TestControl_DataContextChanged;
}
private void TestControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null) Content = new Label() { Content = "TestControllabel"};
else Content = null;
}
}
I'm not looking for a fix of this example app, but for the reason why the font size is not inherited in this special case, so maybe then I can fix my complex app.
Any thoughts would be useful !
Edit: For now I fixed my application by setting the datacontext of the control before setting it as window content.
The code below code is throwing a NullReferenceException. I want to keep the button's background relative to the state of toggle button.
public partial class MainPage : PhoneApplicationPage
{
public static int key;
public MainPage()
{
ImageBrush brush= new ImageBrush();
brush.ImageSource = new BitmapImage(new Uri(#"Images/Music on.png", UriKind.Relative));
if (key == 0)
music.Background = brush; //////NullReferenceException is throwing here
else
music.Background = null;
InitializeComponent();
}
Move the InitializeComponent() method call in your constructor to be the first line of the constructor. The InitializeComponent() method is responsible for creation of your constituent controls on your page. Since you are currently calling it last, your music field is null causing the NullReferenceException.
I am just new to WPF and I am having problems displaying my record. It seems that my records are "shy" when it comes to displaying them, even though I have all my records already.
Code for my App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Window1 window = new Window1();
var viewModel = new Window1ViewModel();
window.PHGrid.ItemsSource = viewModel.ViewModels;
window.Show();
}
Code for Window1ViewModel:
public class Window1ViewModel : ViewModelBase
{
private readonly DAPHContrib _contribRepository;
private ObservableCollection<ViewModelBase> _viewModelBases;
public ObservableCollection<ViewModelBase> ViewModels
{
get
{
if (_viewModelBases == null)
{
_viewModelBases = new ObservableCollection<ViewModelBase>();
}
return _viewModelBases;
}
}
public Window1ViewModel()
{
_contribRepository = new DAPHContrib();
//Create instance of our view model to add it in our collection
PHContribViewModel viewModel = new PHContribViewModel(_contribRepository);
ViewModels.Add(viewModel);
}
}
Here's my Window1.xaml UPDATED:
<Window x:Class="Wabby_App.Views.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Wabby_App.ViewModels"
xmlns:v="clr-namespace:Wabby_App.Views"
Title="Utos ng mahal ko"
Height="300"
Width="300">
<Grid>
<DataGrid
AutoGenerateColumns="True"
Height="200"
HorizontalAlignment="Center"
Name="PHGrid"
VerticalAlignment="Center"
Width="200"
ItemsSource="{Binding ViewModels}"/>
</Grid>
Output:
Hope you can help me with this.
based on your comments you have view models collection (ObservableCollection<ViewModelBase>)
and inside each of these view model base instances (PHContribViewModel) you have another collection ObservableCollection<PHContrib_Entity>.
Hence you have two levels of nested collections and one datagrid to map. This wont work as it is. For this you would need to flatten this 2 level hierarchy of collections into one list of type ObservableCollection<PHContrib_Entity>.
Use LINQ to do that...
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
Window1 window = new Window1();
var viewModel = new Window1ViewModel();
window.PHGrid.ItemsSource
= viewModel.ViewModels.SelectMany(vm => vm.PHContribEntities).ToList();
window.Show();
}
Let me know if this helps...
Your View (Window1) is not binding to ViewModel, it's just setting the control's ItemsSource to a property of the ViewModel which is an incorrect way to implement MVVM. What you need to do is set DataContext of Window1 to instance of ViewModel (Bind View to ViewModel). So, you need to update your code in the OnStartup method.
from
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Window1 window = new Window1();
var viewModel = new Window1ViewModel();
window.PHGrid.ItemsSource = viewModel.ViewModels;
window.Show();
}
to
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Window1 window = new Window1();
var viewModel = new Window1ViewModel();
window.DataContext = viewModel;
window.Show();
}
Update
You also need to set ItemsSource property of datagrid to property in ViewModel
<DataGrid ItemsSource={Binding ViewModels} ..
I am learning WPF and have this simple question.
How do I set fill color to property vi XAML?
<Rectangle Fill="{Binding Path=BackgroundColorf}"
Height="112" Margin="0,84,0,0" VerticalAlignment="Top"
Width="116"/>
public partial class MainWindow : Window
{
/// <summary>
/// Gets or sets the BackgroundColor.
/// </summary>
public SolidColorBrush BackgroundColorf
{
get;
set;
}
public MainWindow()
{
this.InitializeComponent();
BackgroundColorf = new SolidColorBrush(Colors.Red);
}
}
Set the datacontext like this
public MainWindow()
{
this.DataContext = this;
this.InitializeComponent();
BackgroundColorf = new SolidColorBrush(Colors.Red);
}
This should work.But there is little more to be done for making your wpf app scalable like Notifications,Dependency properties etc.I recommend you go through the basics of wpf DataBinding architecture before continuing.Go through the link posted by H.B in the comments
To get you going ...
Add a name to Rectangle
<Rectangle x:Name="MyRect" Fill="{Binding Path=BackgroundColorf}" Height="112" ...
then in the code
InitializeComponent();
MyRect.DataContext = this;
BackgroundColorf = new SolidColorBrush(Colors.Red);
Not the best way of doing things - but at least you'll have a red rectangle :)
if you add this your example will work
public MainWindow()
{
this.InitializeComponent();
this.DataContext = this;
BackgroundColorf = new SolidColorBrush(Colors.Red);
}
but you should really in some wpf books or websites to get the basics.
a very good Book is "WPF 4 Unleashed" from Adam Nathan.