I made a WPF control in a library project and would like to extend it with a new one.
<UserControl x:Class="Genesyslab.Desktop.Modules.ExtensionUtils85.GUI.EmbeddingUserControl"
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"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
</Grid>
</UserControl>
I have tried to extend it like this:
<src:EmbeddingUserControl x:Class="Interaxalab.Desktop.Modules.PrototipoCable.CustomViews.InteractionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="Genesyslab.Desktop.Modules.ExtensionUtils85.GUI"
Name="InteractionWorksheetView" Height="321.613" Width="471.396"
>
<Grid>
<WindowsFormsHost x:Name="windowsFormsHost1" HorizontalAlignment="Left" Height="284" VerticalAlignment="Top" Width="471"/>
</Grid>
</src:EmbeddingUserControl>
However, I get an error message saying that the name "EmbeddingUserControl" does not exist in namespace "Genesyslab.Desktop.Modules.ExtensionUtils85.GUI".
The name clearly does exist, since the xaml.cs can find it, but for some reason the xaml cannot.
Any help would be appreciated.
Long story short - you cannot inherit control with xaml by another control with xaml (and does it makes sense even to do so?). In your case, EmbeddingUserControl does not contain any visual tree elements (just empty grid), so you can just do:
public class EmbeddingUserControl : UserControl {
// some methods, properties of your control
}
Then you can inherit exactly like you do already in your question (don't forget to inherit from EmbeddingUserControl both in xaml file and in code-behind file).
You can also inherit from user control with xaml, if your inherited control does not have xaml itself (so you can add\override logic).
If you need to inherit some visual stuctures - you have to switch from inheritance to composition. That is: your base control provides some placeholders where other controls may be placed, or even better allows to provide templates to format data items (like for example ItemsControl and ItemTemplate property). Then you just fill those placeholders with other controls if necessary.
Related
I have custom ContentControl
public class MyContentControl: ContentControl
{....}
with Content defined in XAML like this
<controls:MyContentControl x:Name="myContentControl">
<controls:MyContentControl.Content>
<controls:UserControl1 />
</controls:MyContentControl.Content>
</controls:MyContentControl>
Content shows in designer and in the device when I launch my application. But when I try to change Content property programmatically, for example
UserControl2 control2 = new UserControl2();
myContentControl.Content = control2;
MyContentControl shows nothing. Using standard ContentControl give the same result.
Any suggestions are welcome.
I followed your code to make simple code sample to test. There's no problem.
public class CustomContentControl:ContentControl
{//......}
<Grid>
<local:CustomContentControl x:Name="content">
</local:CustomContentControl>
</Grid>
MyUserControl1 myUserControl1 = new MyUserControl1();
content.Content = myUserControl1;
<UserControl
x:Class="AppContent.MyUserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppContent"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<TextBox Text="abc"></TextBox>
</Grid>
You might have done some specific settings in your code. #Martin Zikmund's suggestion also was reasonable. You could refer to his suggestion and check your code. After that, if you still could not solve this issue, please provide a Minimal, Complete, and Verifiable example.
This should work. The reason could be that the control does not stretch and is displayed just 0x0 in size. Try to set absolute Width and Height to the control2 and check if it displays. You can also set myContentControl.HorizontalContentStretch and myContentControl.VerticalContentStretch.
You can try running the app in debugger and then use the Live Property Explorer to see what the actual size of the control inside Content is.
Ok, I found out where the things went wrong. I am using different controls for desktop and mobile devices, so I put some of theirs XAML views to the DeviceFamily-Mobile folder. This way they automatically use when needed. I've confused namespaces, because all XAML views in this folder have a root namespace for accessibility reasons. When I was trying to add control to the ContentControl via c#, I didn't resolve namespace where my controls were placed. So I've put XAML view as a childs to the ContentControl, and they staying invisible as none of them has InitializeComponent() method. Adding correct controls with initialization fixed my problem.
I am very grateful for your answers, they pointed me to the right way.
I am developing a Windows 8.1 apps,
and i am following MVVM Pattern
I have a Grid in the Application
<Grid Name="g1">
in which in need to add a existing User Control.
<UserControl
x:Class="CaptureApp.UIComponents.PlayVideo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CaptureApp.UIComponents"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<MediaElement Name="MediaPlay" >
</MediaElement>
</Grid>
</UserControl>
Since View (XAML) is not allowed to know the Control.
What will be the correct way to implement it??
the wordpress blog in the comments uses a datatrigger, which isn't present in windows store apps.
if I understand your question correctly, you're trying to have a view within your grid that is conditionally loaded, so that when there is no data for the user control, it is not rendered in the grid?
you could accomplish this by using a
<ContentControl Content="{Binding PropertyOnViewModel}" ContentTemplateSelector="{StaticResource SomeContentTemplateSelector}" />.
public class SomeContentTemplateSelector : DataTemplateSelector
{
public DataTemplate SomeTemplate {get;set;}
protected override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is null)
return null;
return SomeTemplate;
}
}
and then in a DataTemplate, have your UserControl as a child. This will display nothing when there is no Content bound to the ContentControl, and will otherwise display the supplied DataTemplate. You will need to have a property in the over-arching ViewModel that contains the content for this ContentControl, though, just fyi.
edit: if you're adding multiple items dynamically, then you will want an ObservableCollection<> property on your ViewModel, and use an ItemsControl instead of a ContentControl.
I have a created a usercontrol in my wpf application. I have used it like so:
<Page x:Class="InstallerToolkit.Pages.PageVideosNvr"
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"
xmlns:my="clr-namespace:MyProject.UserControls"
mc:Ignorable="d"
d:DesignHeight="525" d:DesignWidth="1050"
Title="PageVideos">
<Grid>
<my:UserControlVideoPlayer Name="VideoPlayer" Margin="559,74,35,155">
</my:UserControlVideoPlayer>
</Grid>
Now in my C# page I want to access it but the VideoPlayer object doesnt appear when I type its name in the code behind c# page.
What doo I do to access it as I want to set one of its properties.
Give x:Name to your UserControl instead of Name
<my:UserControlVideoPlayer x:Name="VideoPlayer" Margin="559,74,35,155">
It will be accessible now in code behind using this.VideoPlayer.
I would suggest to make it a thumb rule that always use x:Name whenever referring to elements in XAML.
Refer to this for difference between Name and x:Name.
I am basically using a user control for the first time, so hopefully it's just a dumb mistake.
I have a simple user control
<UserControl x:Class="TestProject.WebApp.myUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid>
<sdk:AutoCompleteBox Name="myACB" ItemsSource="{Binding Data}" FilterMode="StartsWith" MinimumPrefixLength="2" >
</sdk:AutoCompleteBox>
</Grid>
</UserControl>
I am using the control in another page (in a stack panel):
<navigation:Page x:Class="TestProject.WebApp.myPageView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:local="clr-namespace:TestProject.WebApp"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation">
<Grid>
<StackPanel Orientation="Horizontal">
<local:myUserControl x:Name="myUC" />
</StackPanel>
</Grid>
</navigation:Page>
The control is in the same namespace as page. Removing the x:Name allows the project to compile and the control functionally works. When x:Name is specified I get an error in the generated code of the page:
Type 'TestProject.WebApp.myUserControl' is not defined.
It happens on these lines of code:
internal TestProject.WebApp.myUserControl myUC;
this.myUC == (TestProject.WebApp.myUserControl)this.FindName("myUC")
I tried with two different controls. Same thing. The generated code has "using TestProject.WebApp;" so I don't know why there is an error only when I have a named instance of the control.
I also cannot seem to use just the Name property. I even tried overloading the NameProperty in the control.
I was able to find a post about this here:
.g.vb file claims that Type X is not defined, even though it is!
Apparently, there is an issue when a project has a service reference (in my case I am using RIA services) and the user control resides in an assembly with the same root namespace as the one you are trying to use it in.
So for me it was,
TestProject.WebApp
Then I tried creating a new project for just the control
TestProject.Controls
Same problem.
Then, when I renamed the project and changed the namespace to
CustomControls
it worked.
Hopefully this saves someone else from some frustration and I really hope this problem can be fixed by MS soon.
What you are showing here should work. What is the default namespace in your project property's? Also did you rename your user control after you created it. Both of those issues could be causing you problems.
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