Adding dynamic controls to Silverlight application after WCF Service Asynchronous Callback - silverlight

I'm trying to add some dynamic controls to my Silverlight page after a WCF call. When I try to add a control to I get an error: Object reference not set to an instance of an object.
Here is a simplified version of my code:
using edm = SilverlightBusinessApplication.ServiceRefrence;
public partial class ListWCF : Page
{
edm.ServiceClient EdmClient = new ServiceClient();
public ListWCF()
{
EdmClient.GetTestCompleted += EdmGetTestCompleted;
EdmClient.GetTestAsync();
}
private void EdmGetTestCompleted(object sender, edm.GetTestCompletedEventArgs e)
{
//This is where I want to add my controls
Button b = new Button();
LayoutRoot.Children.Add(b); //Error: Object reference not set to an instance of an object
}
}
Is it not possible to modify the page after it has been loaded? What am I missing?
Thanks

Yes, it is possible to modify the page after it has been loaded.
The first thing you should do when you meet this kind of exception is to determine which of your variables are null. You should be able to do this via the debugger. Stick a breakpoint on this line of code (or tell VS to break when exceptions are thrown) and inspect the variables. My guess is that LayoutRoot is null.
I cannot see a call to InitializeComponent() in your class constructor. Within a Silverlight user control, this call will invoke the generated class that constructs your XAML and also locates the named elements (x:Name), allowing you to access them from your code.

Related

Bound Value gets reset to the empty string

For my WPF application, I created several UserControls which each have their own ViewModel. The ViewModels are all based on a PageViewModelBase which contains a variable "_context".
The UserControls are presented as pages in a Wizard Dialog, which has its own WizardViewModel. WizardViewModel has the variable _masterContext which is passed to the respective child ViewModels via their constructors. For example,
Child1ViewModel vm = new Child1ViewModel(_masterContext);
and the constructor of Child1ViewModel :
public Child1ViewModel(Context context) : base(context)
and the PageViewModelBase :
protected PageViewModelBase(Context context)
{
_context = context;
}
My intention is to have only 1 _masterContext, which can be accessed via each of the ChildViewModels. And each of the child views can bind to this and supply values to various fields in the master context.
However I am encountering the problem that a field that I bind to TextBox.Text gets reset to "" whenever I switch from childView1 to childView2. I'm not sure is this due to my MMI code, or there are more than 1 instance of _masterContext in the application, i.e. my method above is not doing as it should.
What could be causing this?
Managed to find the culprit resetting the value. I implemented a behavior to handle the TextChanged event of the TextBox. Somehow that used in conjunction with the Binding will cause the value to be reset. Once I took that away, the binding was working fine.
Due to my limited knowledgem I'm unable to explain why. But thanks all for your time.

Access windows forms function from WPF windw

i am trying to call a function in Form1 from WPF window and i am getting the following error
"Reference to a non-shared member requires an object reference."
also getting the same error when trying to access the Public variables in Form1 from wpf window.
is it not possiable to do it?
So according to the MSDN this error, this is a problem with trying to reference instance variables as if they are static.
If your class is Form1, you cannot access methods or variables that are not static by calling Form1.Method(). This won't work ever, not just in WPF. This is pretty basic stuff, you might want to read up more on VB. Check out Shared and Static documentation.
To access, for example, the method Show() on Form1, you must instantiate (create an instance of an object), and call the method on your object. Like this.
Dim frm As New Form1()
frm.Show()

Converting WPF application to UserControl for use in WinForms application via ElementHost

I'm trying to convert this WPF application to WPF UserControl so I could use it in WinForms application via ElementHost. I'm new to WPF and have never even touched it prior to this attempt so I might be going about it completely the wrong way.
I got the UserControl project to compile, however, my StaticResources get underlined in VS with message "The resource 'x' could not be resolved". I've tried moving the xamls with the needed x:Key elements up one level (the same level as the UserControl Dijagram.xaml), but it still cannot resolve them.
In the WinForms app, when trying to add the UserControl through designer by selecting hosted content in ElementHost tasks I get the following error:
An error occured trying to create an object of type
'DijagramLC.Dijagram'. Make sure the type has a default constructor.
(even though default constructor exists).
However, if I add it in codebehind, like this:
wpfUserControl = new Dijagram();
elementHost1.Child = wpfUserControl;
Controls.Add(elementHost1);
the code compiles but throws this runtime error: "System.Windows.Markup.XamlParseException: 'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '20' and line position '4'. ---> System.Exception: Cannot find resource named 'MyToolbar'. Resource names are case sensitive."
I've tried with and without App.xaml and adding ResourceDictionary elements for problematic xamls, but basically, I have no idea what I'm doing :)
I've uploaded the code to my SkyDrive and would really appreciate it if someone could take a look and tell me what I'm doing wrong:
https://skydrive.live.com/redir.aspx?cid=21be1f8e850e85cc&resid=21BE1F8E850E85CC!353
I hate jumping in blindly to new techonoly like this, but I have had no choice this time, and need to know if my requirement is even achievable this way.
You are probably getting the error because you use resources from a resource dictionary which is not loaded. Loading a resource dictionary in the hosting application will probably solve the issue:
// When hosting a WPF usercontrol inside an element host,
// application resources are not loaded, so we need to load them manually.
var resources = new ResourceDictionary
{
Source = new Uri("/UNIT4.MKB.GUI.XAML.Dashboard.Resources;component/resources.xaml", UriKind.Relative)
};
// Check for null reference
if (Application.Current != null)
{
//Merge the loaded ResourceDictornairy with the dummy application Resources.
Application.Current.Resources.MergedDictionaries.Add(resources);
}
The problem is, you need THE default constructor like this:
public CreatedPollsUC()
{
InitializeComponent();
}
If you have any other code in the constructor, the error occures:
public CreatedPollsUC()
{
InitializeComponent();
// ... more code
}
So if you want to use further code in the constructor, you need to apply the control first to the element host. Then you can edit the constructor.

multiple windows

I set up two Windows in my WPF C# Blend project. Now what I would like to know (and I have trouble finding some clear documentation) is how to run both windows on application startup and in what way I can pass code from window to window.
Thanks
In the app.xaml file for the solution, it specifies which window to run upon startup. A quick solution to open the other one is to tack on an event handler to the startup window's Loaded event which opens the second window.
However, that's not too scalable of a solution if this is part of a larger project. Having a separate class which can open each window, then neither window needs to know about the other.
As for passing data between them, using events can offer a more loosely-coupled solution. I'd push for a more MVVM (Model-View-ViewModel) architecture, then let each of the ViewModels raise events that the other can respond to. You can declare your own subclass of EventArgs which would supply the information which needs to be passed.
Update
Sorry for the delay in response. Simply, to have one Window share data with another Window, the receiver must have a way to receive that data. Defining a public property in the receiver will allow the sender to specify the data with a simple property call. By default, a Window's controls are internal, so you can access them within the same assembly, but that's not the best way to do it.
WPF has a really rich binding infrastructure that you should be taking advantage of. Do do this, your object which is providing data to the Window needs to implement the INotifyPropertyChanged interface. This will alert the UI that data has changed, and the binding should update the target with the changed data. The MSDN page describing the interface as well as a sample implementation can be found here.
When you implement that interface, that will expose an event (PropertyChanged) which will fire when data has been changed. The object providing data to the other window can register an event handler to listen for these changes, and then it will have the updated value.
Here's an example implementation of a simple class with a FirstName and LastName property.
class FirstNameViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string firstName;
public string FirstName
{
get { return firstName; }
set
{
if(firstName == value)
return;
firstName = value;
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
}
}
private string lastName;
public string LastName
{
get { return lastName; }
set
{
if(lastName == value)
return;
lastName = value;
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("LastName"));
}
}
}
You can see that there's some code duplication in here--that's often refactored into a base ViewModel class. You'll see that this exposes the PropertyChanged event. Attach an event handler to it, and in the PropertyChangedEventArgs object the handler receives, the PropertyName property will contain the name of the property that was changed (the same as the string passed to the constructor in each of the setters above). The sender parameter will be a reference to the object itself. Cast it to the correct type, and you'll have access to the properties.
Hopefully that gets you a start. I wrote a very contrived sample that I can upload somewhere if you'd like to see it. It opens 2 windows, then you can see that typing in one window causes the typed text to appear in the other one, and vice versa.
If you want to pass data between the windows you should have pointers to the other window in each window. Either that, or you could read up on using a singleton-class. This is handy if you want the windows to share settings, more than sending a lot of data between them.
http://www.yoda.arachsys.com/csharp/singleton.html

load event not fired in inherited user control loaded from another assembly (Winforms)

I have an application with plugin-like structure.
all application forms inherit from a base UserControl :
public class BaseUserControl : UserControl
{
// some common properties and methods
//
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
}
and are compiled in different assemblies.
When I want to show a form, it goes through this sequence:
assembly = Assembly.LoadFile(assemblypath);
.
.
frm = (BaseUserControl)assembly.CreateInstance(frmname);
.
.
SomeContainer.Controls.Add(frm);
MainScreen.Controls.Add(SomeContainer);
Common structure of these forms is :
public class TestForm : BaseUserControl {
public TestForm(){InitializeComponent();}
private void InitializeComponent(){
.
.
this.Load += new System.EventHandler(this.TestForm_Load);
.
}
private void TestForm_Load(object sender, EventArgs e){}
}
The problem is that the Load event of these forms does not get fired.
Another behavior, I don't understand how, when setting a break point at the OnLoad in the base class, the call stack shows that is called from within the InitializeComponent.
Any ideas on how to solve this?
You are hopelessly mixing up the terms Form and UserControl, making it very hard to give a good answer. They are very different beasts, you can't turn a UC into a form. It is a client window, not a top-level window. I suspect that has something to do with your problem but the generic diagnostic is that somebody is overriding OnLoad and not calling base.OnLoad().
Yes, OnLoad may be called from code in InitializeComponent(). It isn't very healthy since OnLoad will run before the constructor is finished, but it is supported. This will happen when you touch a property that requires the Handle to be created. The call stack should show you which particular property assignment did this, just double-click the line in the call stack.

Resources