In Java, I use an extends View to create a custom View. How to do it on c#?
You can either create an element using the XAML and associating the layout to any element?
In WPF you need to create custom user control. Start with that empty xaml file and you can define your own layout, then fill the grid with other controls and etc. The code behind is in MyCustomControl.cs file.
<UserControl
Name="MyCustomControl"
x:Class="MyCustomControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
<Grid x:Name="LayoutRoot">
</Grid>
</UserControl>
The code behind looks similar to this:
public partial class MyCustomControl: UserControl
{
public MyCustomControl()
{
InitializeComponent();
}
}
Related
I have a XAML control which gets loaded dynamically at runtime. This is pure XAML with no code behind.
I dont have any control over the parent loading mechanism which is why this looks a bit weird.
I have a parent application which loads my Plugin DLL and loads my XAML Control.
My DLL signature is:
public class Application : BaseClassHere
{
public Application(IParentContext context) : base(context)
{
// Im placing this instance in the bag which i use in my XAML
base.MyObservablePropertyBag["MyParentContext"] = new ObservableValue<object>(this);
}
}
My XAML is like this:
<av:UserControl
xmlns:local="clr-namespace:MyApplicationNS;assembly=MyDll"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" >
<Border DataContext="{Binding MyObservablePropertyBag[MyParentContext].Value}" >
<Button Name="MyButton" />
</Border>
</UserControl>
This binding works perfectly in the XAML. I have full access to all public properties that i definein the Application class.
My problem is that i want to link to up Click events on my Buttons. If i add a Click event in the XAML it errors at runtime telling me that i need to compile my XAML.
Is there any way to subscribe to the Click event on MyButton in the Application class?
Well, if you say binding works then why try to mess with the Click event? Rather go with the Button's Command property. Create an ICommand instance (like a DelegateCommand or RelayCommand) that you place in your propertybag and just bind to it!
I just created a windows Form application to inherit controls from base form and it works fine.
In WPF XAML is it possible to inherit controls from a base form to another like above?
When I tried in visual studio, I have got an error showing:"'parentchild.MainWindow' cannot be the root of a XAML file because it was defined using XAML".
My Basewindow cs code:
namespace parentchild
{
public partial class BaseWindow : Window
{
public BaseWindow()
{
InitializeComponent();
}
}
}
My Basewindow xaml code:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxr="http://schemas.devexpress.com/winfx/2008/xaml/ribbon" x:Class="parentchild.BaseWindow"
Title="BaseWindow" Height="350" Width="525">
<Grid>
<StatusBar HorizontalAlignment="Left" Height="35" Margin="0,285,0,0" VerticalAlignment="Top" Width="517">
<Label Content="Label"/>
<Label Content="Label"/>
</StatusBar>
</Grid>
</Window>
My childwindow cs code:
namespace parentchild
{
public partial class childwindow : BaseWindow
{
public childwindow()
{
InitializeComponent();
}
}
}
My childwindow xaml code:
<mn:BaseWindow x:Class="parentchild.childwindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mn="clr-namespace:parentchild"
Title="childwindow" Height="300" Width="300">
<Grid>
</Grid>
</mn:BaseWindow>
I found another solution by creating an user control and applying it to all windows.Is that the right way?
Or anybody have solution for creating a general theme/structure for all Xaml windows.
Please provide me a solution to solve this issue.
You cannot inherit from a class that has been defined in xaml. I would probably go with creating a UserControl and using that as a 'base container' in any Window you want to have the status bar. If you are intent on making a base Window you could try something like this:
Define the base Window in code only:
public class MyWindowBase : Window
{
private ContentControl contentControl;
public MyWindowBase()
{
this.CreateContent();
}
public Object BaseContent
{
get { return this.contentControl.Content; }
set { this.contentControl.Content = value; }
}
private void CreateContent()
{
var grid = new Grid();
var row1 = new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) };
var row2 = new RowDefinition() { Height = GridLength.Auto };
grid.RowDefinitions.Add(row1);
grid.RowDefinitions.Add(row2);
var statusBar = new StatusBar() { Height = 35, Background = Brushes.Blue }; // Initialize the status bar how you want.
Grid.SetRow(statusBar, 1);
this.contentControl = new ContentControl();
grid.Children.Add(this.contentControl);
grid.Children.Add(statusBar);
base.Content = grid;
}
}
Use the base window in xaml like this:
<WpfApplication7:MyWindowBase xmlns:WpfApplication7="clr-namespace:WpfApplication7" x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="500">
<WpfApplication7:MyWindowBase.BaseContent>
<Button>
Something
</Button>
</WpfApplication7:MyWindowBase.BaseContent>
</WpfApplication7:MyWindowBase>
Of course the base class has room for improvement, like making BaseContent a dependency property, but I think it demonstrates the main idea.
It looks like you are basically trying to create a custom control that extends Window. Creating custom controls in WPF is a complex topic because there is a lot to consider when deciding how to implement one. Take a look at this article that talks about this:
Control Authoring Overview
Most likely, you do not actually want a custom control, but rather a custom ControlTemplate (authored in xaml) that redefines how you want your window to look. You can define the template in a Style and apply that style to any Window that you want. It is a lot to try to explain here in an answer, so you should read up on how control templates work and how they are useful.
If you decide you need to add new properties to your custom window, then you will want to make a new class that extends Window and adds those properties as dependency properties (now you have a custom control). You can then use those properties in your custom ControlTemplate to do whatever you want them to do.
Working in WPF is not at all like working in Windows Forms. If you try to apply techniques and practices you learned in Windows Forms to a WPF application, you will cause yourself a lot of headaches. I made that transition a couple years ago, and my advice is to make no assumptions about WPF based on what you know from Windows Forms. They are completely different systems with different ways of doing things.
So in Caliburn Micro, I have been using the following method to compose a view inside of another view:
Put a ContentControl inside the composing View.
Create a property on the composing ViewModel, and assign to it the composed ViewModel
Give the ContentControl a x:Name attribute that matches the name of the composed ViewModel property on the composing ViewModel.
like so...
View:
<UserControl x:Class="MyProject.MyComposingView"
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">
<ContentControl x:Name="MyComposedViewModel"/>
</UserControl>
ViewModel:
class ComposingViewModel : PropertyChangedBase
{
private ComposedViewModel _myComposedViewModel;
public ComposedViewModel MyComposedViewModel
{
get { return _myComposedViewModel; }
set
{
_myComposedViewModel= value;
NotifyOfPropertyChange(() => Page);
}
}
public ComposingViewModel(ComposedViewModel myComposedViewModel)
{
MyComposedViewModel = myComposedViewModel;
}
}
Caliburn Micro automagically figures out that because it's a ContentControl it obviously doesn't want to bind to a ViewModel, but rather to its associated View, and so it does something under the hood to bind the ContentControl's Content property to MyComposedView instead of MyComposedViewModel.
But, what if I don't want to use a ContentControl? Like, maybe some reusable custom component of mine that wraps a ContentControl instead? For example:
<UserControl x:Class="MyProject.MyContentWrapper"
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 x:Name="PreviewBox" SizeChanged="onSizeChanged">
<Image x:Name="BGImage" Source="{Binding BGImage}"/>
<ContentControl Content="{Binding}"/>
</Grid>
</UserControl>
If I replace the ContentControl with a MyContentWrapper, CaliburnMicro no longer works its magic to supply MyComposedView, and I end up with a TextBlock that says, MyProject.MyComposedViewModel.
How can I get CaliburnMicro to know this is a situation where it should supply the View rather than the ViewModel?
What you want to do is add a convention for your custom control:
Go to the code for ConventionMananger on github.
Search for AddElementConvention<ContentControl>.
Create a new method in your Bootstrapper that runs when your application starts. Add a call to ConventionManager.AddElementConvention<YourControl> similar to the one for ContentControl.
Make sure to put a ContentPropertyAttribute on your control and specify the content property.
Disclaimer: I'm on mobile and can't validate this.
I've been working on a commandline application, and have recently decided to add a wpf window to the application. I added this as a UserControl, however I noticed I can't call this class using ShowDialog() from my main code;
I've tried changing the Base class from a UserControl to Window, however an error occurs;
public partial class UserControl1 : Window
{
public UserControl1()
{
InitializeComponent();
}
Error 1 Partial declarations of
'ExcelExample.UserControl1' must not
specify different base
classesExcelExample
I've added all the references found in my other WPF application to no avail. Help!
In order to change the base class it is not sufficient to change it in code only. You must also change the root tag and any nested elements in accompanying XAML file. For example, you have something like:
<UserControl x:Class="Your.Namespace.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
</UserControl.Resources>
</UserControl>
You must change it to something like:
<Window x:Class="Your.Namespace.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
</Window.Resources>
</Window>
I found something about this issue for ASP, but it didn't help me much ...
What I'd like to do is the following: I want to create a user control that has a collection as property and buttons to navigate through this collection. I want to be able to bind this user control to a collection and display different controls on it (containing data from that collection).
Like what you had in MS Access on the lower edge of a form ...
to be more precise:
When I actually use the control in my application (after I created it), I want to be able to add multiple controls to it (textboxes, labels etc) between the <myControly> and </mycontrol>
If I do that now, the controls on my user control disappear.
Here is an example of one way to do what you want:
First, the code - UserControl1.xaml.cs
public partial class UserControl1 : UserControl
{
public static readonly DependencyProperty MyContentProperty =
DependencyProperty.Register("MyContent", typeof(object), typeof(UserControl1));
public UserControl1()
{
InitializeComponent();
}
public object MyContent
{
get { return GetValue(MyContentProperty); }
set { SetValue(MyContentProperty, value); }
}
}
And the user control's XAML - UserControl1.xaml
<UserControl x:Class="InCtrl.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300" Name="MyCtrl">
<StackPanel>
<Button Content="Up"/>
<ContentPresenter Content="{Binding ElementName=MyCtrl, Path=MyContent}"/>
<Button Content="Down"/>
</StackPanel>
</UserControl>
And finally, the xaml to use our wonderful new control:
<Window x:Class="InCtrl.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:me="clr-namespace:InCtrl"
Title="Window1" Height="300" Width="300">
<Grid>
<me:UserControl1>
<me:UserControl1.MyContent>
<Button Content="Middle"/>
</me:UserControl1.MyContent>
</me:UserControl1>
</Grid>
</Window>
I'm having a hard time understanding your question, but I think what you're describing is an ItemsControl using DataTemplates to display the contents of (presumably) an ObservableCollection(T).
A UserControl may not be the best way to do this. You're wanting to add decorations around content, which is basically what Border does: it has a child element, and it adds its own stuff around the edges.
Look into the Decorator class, which Border descends from. If you make your own Border descendant, you should be easily able to do what you want. However, I believe this would require writing code, not XAML.
You might still want to make a UserControl to wrap the buttons at the bottom, just so you can use the visual designer for part of the process. But Decorator would be a good way to glue the pieces together and allow for user-definable content.
Here's a link to a built-in control (HeaderedContentControl) that does the same thing as the accepted answer except that it is an existing control in WPF since .Net 3.0