Change button's background image from constructor of MainPage class - silverlight

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.

Related

Change Visibility of Main Window from a different window

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;

Problems implementing ColorAnimation in Ellipse Fill

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);

TabControl region, How to pass parameter to child region? WPF - Prism

I'm using prism regions in order to create dynamic TabControl. But I'm having a problem passing the object from TabItem (parent view) to its child regions.
The below is the code I'm using to build the TabControl.
Shell:
xaml
<ContentControl regions:RegionManager.RegionName="ShellProjectRegion" />
ShellViewModel
regionManager.RegisterViewWithRegion(ShellProjectRegion, typeof(ProjectTabView));
ProjectTabView:
xaml
<TabControl regions:RegionManager.RegionName="ProjectTabRegion">
ProjectTabViewModel
container.RegisterType<object, ProjectView>(typeof(ProjectView).FullName);
ProjectView:
xaml
<Grid>
<ContentControl regions:RegionManager.RegionName="ProjectExplorerRegion"
regions:RegionManager.RegionContext="{Binding}" />
</Grid>
ProjectViewModel
public class ProjectViewModel : BindableBase, INavigationAware, IActiveAware {
private ProjectItem _project;
public ProjectItem Project {
get { return _project; }
set { SetProperty(ref _project, value); }
}
public ProjectViewModel(IRegionManager regionManager) {
regionManager.RegisterViewWithRegion("ProjectExplorerRegion", typeof(ProjectExplorerView));
}
public void OnNavigatedTo(NavigationContext navigationContext) {
Project = (ProjectItem)navigationContext.Parameters["project"];
}
}
ProjectExplorerView:
xaml.cs
public ProjectExplorerView(IUnityContainer container) {
InitializeComponent();
var vm = container.Resolve<ProjectExplorerViewModel>();
RegionContext.GetObservableContext(this).PropertyChanged += (s, e) => {
var context = (ObservableObject<object>)s;
var projectVm = (ProjectViewModel)context.Value;
vm.ParentProjectInfo = projectVm.Project.ProjectInfo;
};
DataContext = vm;
}
Note: Please note that in the last piece of code inside the ProjectExplorerView.xaml.cs the view constructor gets called multiple times each time new Tab is created. when tracing the code, the context variable gets null sometimes, and sometimes has the right value, which is the project I want to pass. but the it's always null at the end of calling the constructor.
So I'm not sure if this is the right way to do it, but it works.
First I've removed regionManager.RegisterViewWithRegion("ProjectExplorerRegion", typeof(ProjectExplorerView)); from ProjectViewModel to ShellViewModel, this was causing the view to be called multiple times as I have mentioned at the end of my question.
Second update the ParentProjectInfo implementation to use INotifyPropertyChanged, and inside the property setter, update what needs to be automatically updated.

How to pass initialization parameters to UserControl in WPF (using MVVM)

I have a UserControl called ActionsTreeView I built using MVVM practices where I have an IPluginsProvider interface that populates the data in my UserControl. I want to be able to provide an object implementating this IContentProvider interface as a parameter to initialize my UserControl's ViewModel.
Here is my approach so far, which isn't working. I am wondering if I'm going down the right path? I declare a DependencyProperty in my user control which is visible to my mainWindow where I want to instantiate this UserControl. This code just attempts to pass the PluginsProvider object to my UserControl which needs it to build its ViewModel.
My PluginProvider DependencyProperty setter in my UserControl never gets hit because my My PropertyChanged handler is always null in MainWindow.xaml.cs I think I have the code right, but not sure I'm going down the right road and what I'm missing to make this connection?
ActionsTreeView.xaml.cs
public partial class ActionsTreeView: UserControl
{
public static readonly DependencyProperty PluginProviderProperty = DependencyProperty.Register("PluginProvider", typeof(Models.IPluginsProvider), typeof(ActionsTreeView), new FrameworkPropertyMetadata(null, OnPluginProviderChanged));
private ViewModels.ActionsTreeViewModel vm;
public ActionsTreeView()
{
//Wire-up our ViewModel with the data provider and bind it to DataContext for our user control
//This is a Mock-up until I figure out a way to get the real provider here
Models.IPluginProvider pluginSource = new Models.MockPluginProvider();
vm = new ViewModels.ActionsTreeViewModel(pluginSource );
this.DataContext = vm;
InitializeComponent();
}
private static void OnPluginProviderChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
((ActionsTreeView)source).PluginProvider = (Models.IPluginsProvider)e.NewValue;
}
public Models.IPluginsProvider PluginProvider
{
get
{
return (Models.IPluginsProvider)GetValue(PluginProviderProperty);
}
set
{
SetValue(PluginProviderProperty, value);
vm.SetPluginSource(PluginProvider);
}
}...
MainWindow.xaml.cs
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public MainWindow()
{
InitializeComponent();
this.ActionProvider = new Models.PluginsProvider(Library.Action.AvailableActions);
}
private Models.IPluginsProvider _actionProvider;
public Models.IPluginsProvider ActionProvider
{
get { return _actionProvider; }
set
{
_actionProvider = value;
OnPropertyChanged("ActionProvider");
}
}
protected void OnPropertyChanged(string property)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) //HANDLER IS ALWAYS NULL
{
handler(this, new PropertyChangedEventArgs(property));
}
}
}
Using my UserControl in MainWindow.xaml
<Grid>
<UserControls:ActionsTreeView PluginProvider="{Binding ActionProvider}" />
</Grid>
I don't think you can pass a parameter in the ctor in xaml.
If you create control in code behind you can pass the parameter in the ctor(Param param)
Not sure if this fits in the MVVM model but I use it a lot in regular code behind
Use a frame in the XAML for a place to put the UserControl
Seems like you are missing the binding source
<Grid>
<UserControls:ActionsTreeView PluginProvider="{Binding ActionProvider, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" />
</Grid>
since your property ActionProvider is declared in MainWindow so during binding you are required to refer the same source unless you've set it as data context of the window
alternative to above you can also do the below if there is no other data context used in the MainWindow then you can use the original binding you have PluginProvider="{Binding ActionProvider}"
public MainWindow()
{
InitializeComponent();
this.ActionProvider = new Models.PluginsProvider(Library.Action.AvailableActions);
DataContext = this;
}
I've set the DataContext to this which will effectively resolve the value of ActionProvider in binding from the instance this
Extra
you may also choose to remove INotifyPropertyChanged from MainWindow as it is already DependencyObject and capable of property notification and declare a DependencyProperty for ActionProvider
eg
public Models.IPluginsProvider ActionProvider
{
get { return (Models.IPluginsProvider)GetValue(ActionProviderProperty); }
set { SetValue(ActionProviderProperty, value); }
}
// Using a DependencyProperty as the backing store for ActionProvider. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ActionProviderProperty =
DependencyProperty.Register("ActionProvider", typeof(Models.IPluginsProvider), typeof(MainWindow), new PropertyMetadata(null));
so you don't need to worry for the notification change manually, you might be required to use this if the above solution does not work for you otherwise it is good to have.

Open new UserControl in the mainWindows

public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
switch ((sender as Button).Content.ToString())
{
case "UserControl 1":
AddItemToContainer(new UserControl1());
break;
case "UserControl 2":
AddItemToContainer(new UserControl2());
break;
case "UserControl 3":
AddItemToContainer(new UserControl3());
break;
default:
break;
}
}
void AddItemToContainer(UIElement _myElement)
{
Grid.SetColumn(_myElement, 1);
HostContainer.Children.Add(_myElement);
}
}
}
}
With this I can open a new userControl in myMainwindow
Let’s say something like adding child to myMainWinodw,Now I’m trying to click on a button from my userControl so I open another userControl that take the place of the first one
I explain:
I have the mainWindows it has 3 button first one to open the first UserControl the second one to open the second userControl and the third to open the last UserControl,imagine that I opened the first UserControl let’s call it UC1,
In the UC1 I have a button to open the second userControl (let’s call it UC2) I like that when I clik the button from the UC1 the UC2 is opened and take the place of the UC1 (of course the UC2 is still a child of myMainWinodw)
I have alredy try to call the AddItemToContainer methode from other methode but nothing is happened
Any suggestion please
This approach may help:
Call the container control and modify it's Children.This example assumes that the container control is a Grid.
C# Code for Window1
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
HostContainer.Children.Add(new UserControl1(HostContainer));
}
}
C# Code for UserControl1
public partial class UserControl1 : UserControl
{
Grid _hostContainer;
public UserControl1(Grid HostContainer)
{
InitializeComponent();
_hostContainer = HostContainer;
}
private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
UserControl2 UC2 = new UserControl2();
_hostContainer.Children.Add(UC2);
}
}
Yes that helps but it does not realy take the place of the UC1 It just puch it a litel bit and take a litelle space of the mainWindow here is some snaps with explanation if you like http://startou.com/file/630-9411954b18.html

Resources