I would like to develope a WPF User Control Library that uses a Class Library with a member function that can be over-ridden . I’m using C# 4.0 and VS 2010.
My test class library looks like:
using System.Diagnostics;
namespace MyLibrary {
public class Foo {
virtual public void Bar() {
Debug.WriteLine(" Hi from MyLibrary, class Foo, method Bar.");
}
}
}
My WPF User Control looks like:
using System.Windows.Controls;
using System.Diagnostics;
using MyLibrary;
namespace MyUserControl {
public partial class UserControl1 : UserControl {
public UserControl1() {
InitializeComponent();
Debug.WriteLine("MyUserControl: ");
var foo = new Foo();
foo.Bar();
}
}
}
I have built a WPF Application called ProgramA, and it looks like:
using System;
using System.Diagnostics;
using System.Windows;
namespace ProgramA {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
}
}
When debugging ProgramA, you will see:
MyUserControl:
Hi from MyLibrary, class Foo, method Bar.
in the debug Output window. So far, so good.
I have also built ProgramB to try to override the Bar method of MyLibrary.
ProgramB looks like:
using System.Windows;
namespace ProgramB {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
}
}
The XML for both ProgramA and ProgramB contains a reference to MyUserControl:
<Window x:Class="ProgramB.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"
xmlns:my="clr-namespace:MyUserControl;assembly=MyUserControl">
<Grid>
<my:UserControl1 Name="userControl11"
HorizontalAlignment="Left"
VerticalAlignment="Top" />
</Grid>
</Window>
I have added a Class to ProgramB's project called NewFoo.cs, and it looks like:
using System.Diagnostics;
using MyLibrary;
namespace ProgramB {
class NewFoo : MyLibrary.Foo{
override public void Bar() {
Debug.WriteLine(" Hi from ProgramB Foo, method Bar.");
}
}
}
ProgramB compiles and runs, but the output is:
MyUserControl:
Hi from library Foo, method Bar.
The override did not work.
Here is the problem. The Namespace for ProgramB’s Foo method is ProgramB, and hence it does not override the Bar method of MyLibrary.
Is there a way ProgramB can override the Bar method used by MyUserControl?
Any help or suggestions will be greatly appreciated.
Charles
Its because UserControl1 doesnt know about NewFoo and only instantiates Foo. It has nothing to do with namespaces.
The override will work, as long as you provide the correct instance.
You should expose a property in UserControl1 where you can set what foo to use.
Related
I am c# web application beginner using silverlight 5. before i was working on c# console applications and there i had body of code working like this.
namespace check
{
public class main
{
public void FunctionDefinition1()
{
//Inside something
}
}
public class second
{
public static void Main(string[] args)
{
main object = new main();//this is how the objects were created and here the constructor was called.
object1.FunctionDefinition1(); //I was calling the FunctionDefinition1 like this here
}
}
}
But when i tried to create a web application in c# silverlight (asp.net web application). I don't know how to call a function definition from other class and how and where the objects are created in that class ?
I have created a small project names as "Fun". see the code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace Fun
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
public void merge(int head)
{
MessageBox.Show("check1");
}
}
public class she
{
MainPage obj1 = new MainPage();
obj1.merge(1); //It is not working gives red line, means error.
}
}
Could some one please explain me using this code silver light c# code that:
(1) How the Objects of the classes are created (I mean constructor is initialized when we create the object of that class, Is it same here, If yes then why it is giving red line in VS 2010 here on merge() function call using Object of MainPage class).
(2) what does this InitializeComponent(); do ?
(3) Why there is no public static void Main(string[] args) function inside it ? So how the control passes by compiler.
(4) Suppose if i inserted one button in GUI so now the code changed to this :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace Fun
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
public void merge_sort(int head)
{
MessageBox.Show("check1");
}
private void button1_Click(object sender, RoutedEventArgs e)
{
}
}
public class she
{
MainPage obj1 = new MainPage();
obj1.button1_Click(....);//It don't recognize "obj1" object. Why ?
}
}
Now is it possible to call the button1_Click() function from another class "she" ? Thanks if some one could explain me how the compiler's control go on this c# code whereas i am not able to see any " public static void Main(string[] args)" function.
Big thanks for answering these question.
UPDATED
I think I found your error.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace Fun
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
merge_sort();
}
public void merge_sort()
{
she Object1 = new she();
Object1.DoMethod(2);//Now this will do your work.
}
}
public class she
{
public void DoMethod(int head)
{
//Do what do you want
}
}
}
Please Explain how do access the Class she?
2). InitializeComponent();
In my words I think it has the all your output, and also it's exists in the compiled assembly .
3). public static void Main(string[] args);
In WPF Silverlight WP8 application do not need this, Because when App.Xaml is build Main method will automatically generated.If you look at the project properties you'll find there's a setting for you to choose the startup object. So if you want, you can provide your own class that implements Main().
I'm new in WPF and I'm doing following code below as:
public partial class MainView : ViewModelControl
{
public MainView()
{
InitializeComponent();
this.DataContext = new ViewModel1();
}
}
As you can see I have my own class ViewModelControl. I have the following code below fro ViewModelControl class as:
public partial class ViewModelControl : Window, IViewModelControl
{
public virtual void bindFirstDataContext()
{
}
public virtual void bindSecondDataContext()
{
}
}
I Modify the following XAML as:
<Window x:Class="WpfApplication1.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainView" Height="262" Width="316">
Now the issue is that its show's error "Partial declarations of 'WpfApplication1.View.MainView' must not specify different base classes". It's not working as before as When I implement it with Window class as by default. Where I'm doing wrong?
Base class for partial class declarations should be same. You have changed Window in code behind to ViewModelControl so that needs to be updated in XAML as well.
Change XAML declaration to this:
<local:ViewModelControl
x:Class="WpfApplication1.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Namespace"> <-- HERE replace Namepsace with
actual namespace of class
ViewModelControl.
....
</local:ViewModelControl/>
You need to change your XAML:
<src:ViewModelControl x:Class="WpfApplication1.Interface.MainView"
xmlns:src="clr-namespace:WpfApplication1.Interface" ...>
</src:ViewModelControl>
This will work, be carefull in the class attribute, write the fullname of your class ("namespace"."name of the class")
After "xmlns:src="clr-namespace:" you need to write the namespace where ViewModelControl is.
It need to be like that because MainView doesn't inherit directly from Window so you can't put a class name in the class attribute of a Window if it's not a direct child of window.
With this change it should work I tried it, if you still have some problem look again the namespace names it's easy to get confused.
I am making a MessageBox like class (MessageBoxCustom).
I would like to have a Form with designer support in a separate file so I can modify the appearance through Visual Studio (MessageBoxCustomDialog ).
I would also like to make this MessageBoxCustomDialog unreachable by code outside MyMessageBox and I'm nesting MessageBoxCustomDialog. I would like to move it in a separate file so I'd have designer support. Maybe using a partial class? How would the hierarchy go?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace System.Windows.Forms
{
public static class MessageBoxCustom
{
public static void Show()
{
(new MessageBoxCustomDialog()).ShowDialog();
}
private class MessageBoxCustomDialog : Form
{
}
}
}
The Visual Studio Designer can not help you design nested classes. It is just not made for that. It checks the type of the first outermost class in the file and then decides which designer to use.
If it is just about designing the layout of the form I would recommend to design it as usual. When you finished your project you can then surround the class by the outer class (in both files) and make it private.
When you finshed your work just copy and paste the dialog class into the outer class and make it private. If you have to rework the design it is again just copy and paste.
MessageBoxCustomDialog.cs:
namespace System.Windows.Forms
{
// make sure this is the first class in the file (required by designer)
public partial class MessageBoxCustomDialog : Form
{
public MessageBoxCustomDialog()
{
InitializeComponent();
}
}
public static partial class MessageBoxCustom
{
public static void Show()
{
new MessageBoxCustomDialog().ShowDialog();
}
// put the MessageBoxCustomDialog class here when you are done
}
}
MessageBoxCustomDialog.Designer.cs:
namespace System.Windows.Forms
{
partial class MessageBoxCustomDialog
{
...
}
partial class MessageBoxCustom
{
// put the MessageBoxCustomDialog class here when you are done
}
}
Make your MessageBoxCustomDialog a private partial inner class
private partial class MessageBoxCustomDialog : Form
{}
You must make MessageBoxCustom partial having same scope of MessageBoxCustomDialog
File 1
using System.Windows.Forms;
namespace System.Windows.Forms
{
public static partial class MessageBoxCustom
{
public static void Show()
{
(new MessageBoxCustomDialog()).ShowDialog();
}
private partial class MessageBoxCustomDialog : Form
{
}
}
}
File 2
using System.Windows.Forms;
namespace System.Windows.Forms
{
public static partial class MessageBoxCustom
{
private partial class MessageBoxCustomDialog : Form
{
// designer code
}
}
}
You may see this link http://msdn.microsoft.com/en-us/library/wa80x488.aspx [Restrictions section]
I have this code behind:
CustomUserControl.xaml.cs
namespace MyProject
{
public partial class CustomUserControl<T> : UserControl
{
...
}
}
and this xaml:
CustomUserControl.xaml
<UserControl x:Class="MyProject.CustomUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Grid>
</Grid>
It doesn't work since the x:Class="MyProject.CustomUserControl" doesn't match the code-behind's generic class definition. Is there some way to make this work?
You can create generic "code-behind" file without XAML-file:
public class CustomUserControl<T>: UserControl
{ }
and than derive from it providing specific class as a parameter:
public partial class SpecificUserControl : CustomUserControl<Presenter>
{
public SpecificUserControl()
{
InitializeComponent();
}
}
XAML:
<application:CustomUserControl
x:TypeArguments="application:Presenter"
xmlns:application="clr-namespace:YourApplicationNamespace"
...
Unfortunately, it seems that Visual Studio designer doesn't support such generics until Visual Studio 2012 Update 2 (see https://stackoverflow.com/a/15110115/355438)
Haven't found my solution anywhere else so far.
The main difference is, that I have got one .xaml file
for the generic user control class and not one for each actual user control.
GenericUserControl.xaml.cs
using System.Windows.Controls;
namespace TestGenericUserControl
{
public abstract partial class GenericUserControl : UserControl
{
// If you use event handlers in GenericUserControl.xaml, you have to define
// them here as abstract and implement them in the generic class below, e.g.:
// abstract protected void MouseClick(object sender, MouseButtonEventArgs e);
}
public class GenericUserControl<T> : GenericUserControl
{
// generic properties and stuff
public GenericUserControl()
{
InitializeComponent();
}
}
// To use the GenericUserControl<T> in XAML, you could define:
public class GenericUserControlString : GenericUserControl<string> { }
// and use it in XAML, e.g.:
// <GenericUserControlString />
// alternatively you could probably (not sure) define a markup extension to instantiate
// it directly in XAML
}
GenericUserControl.xaml
<UserControl x:Class="TestGenericUserControl.GenericUserControl"
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"
mc:Ignorable="d">
<Grid>
<Label Content="hello" />
</Grid>
</UserControl>
Unfortunately XAML does not support generic code behind, thou you can walk around this.
See links below:
http://forums.silverlight.net/forums/p/29051/197576.aspx
Can I specify a generic type in XAML (pre .NET 4 Framework)?
May be generic controls will be supported natively in future versions of Visual Studuo with
XAML 2009.
I ended up with an extra helper class, this is not a UserControl. It does the job well for a simple custom UserControl that needs a Generic Type.
So the UserControl, for instance UCMoveObject, has an InitFunction that returns to me the Helper instance:
// In the UCMoveObjects UserControl Class.
public UCMoveObjectsHelper<T> InitUCMoveObject<T>(List<T> argAllList, List<T> argSelectedList)
{
return new UCMoveObjectsHelper<T>(this, argAllList, argSelectedList);
}
Then in the helper class I place all the code for making the user control work.
public class UCMoveObjectsHelper<T>
{
public UCMoveObjectsHelper(UCMoveObjects argUserControl, List<T> argAllList, List<T> argSelected)
{
_ucMoveObjects = argUserControl;
// Example reaching the usercontrol
_ucMoveObjects.listBox.SelectionChanged += LbAll_SelectionChanged;
// Do whatever I want with T
}
public List<T> ReturnSelected()
{
// Code that return a List<T>;
}
}
In the MainWindow.xaml i place a usercontrol in the window. Then in code I do the following:
_ucMovingObjectsHelper = ucMovingObjects.InitUCMoveObject<TblUsers>(tempListAll, tempListSelected);
And later in my code I can call:
var tempSelectedList = _ucMovingObjectsHelper.ReturnSelected();
I can modify/access controls and MessageBox with ease in the MainWindow.xaml.cs file of my WPF application. However, when I create some folders and add classes there, I no longer have access to MessageBox nor do I have see the control names in the Intellisense dropdown.
(This seems quite elementary but I'm new to C# and WPF)
You must be missing a namespace. You could do something like this:
MainWindow.cs:
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace YourNameSpaceHere
{
public partial class MainWindow : Window
{
internal static string message_ = string.Empty;
MainWindow()
{
InitializeComponent();
SetupMessage();
}
private void SetupMessage()
{
message_ = "Hello World!";
}
}
}
OtherFile.cs :
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls; //are you missing this namespace?
namespace YourNameSpaceHere
{
public class Messaging
{
Messaging()
{
MessageBox.Show(MainWindow.message_);
}
}
}
Note that I am using the same namespace in each file and by using the internal keyword the message can be accessed by anything as long as it is in the same namespace. I hope this helps!
Does your classes have the right using statement in that would allow you access to the class you are attempting to access within the new classes you've created?