I want to make my own control, inheriting from GroupBox.
Ive followed instructions in here, and that's the result of the implementation:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GeneralUserControls
{
public partial class MyGroupBox : GroupBox
{
public MyGroupBox ()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
}
}
But when I try to use it this way:
<Window [...]
xmlns:guc="clr-namespace:GeneralUserControls;assembly=GeneralUserControls" >
[...
<guc:MyGroupBox Header="Etiquette :" Width="70" Height="70">
<Grid>
[...]
</Grid>
</guc:MyGroupBox>
It seems to not consider it as a groupbox! Here are the errors:
Error 1 The property 'Header' was not found in type 'MyGroupBox'.
Error 2 The type 'MyGroupBox' does not support direct content.
Error 3 Cannot add content to an object of type "MyGroupBox".
Error 9 Cannot add content to object of type 'GeneralUserControls.MyGroupBox'.
Any idea?
You try to mix WPF with WinForms. I see the namespace using System.Windows.Forms; You need to make a WPF custom control, or if you really want a WindowsForms control, you need to wrap it in a WindowsFormsHost control.
The namespace of the GroupBox in WPF is System.Windows.Controls. According to the link you provided, I think you read the wrong tutorial.
You could read for example this: http://wpftutorial.net/HowToCreateACustomControl.html
Related
This question already has answers here:
Why does WPF support binding to properties of an object, but not fields?
(2 answers)
Notify binding for static properties in static classes
(1 answer)
Closed 8 months ago.
I'm very new to C# and XAML. I'm trying to do a WPF project where there will be a good amount of data binding. Right now, I am able to do one way data binding without any problems, the issue I am facing is when I try to do two-way data binding.
This is the beginning of my Xaml file where I try to bind a text box to a static property in a static class:
<Window x:Class="interactive_fountain.MainWindow"
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"
xmlns:local="clr-namespace:interactive_fountain"
xmlns:include="clr-namespace:interactive_fountain.Include"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBox x:Name="ip_textBox" HorizontalAlignment="Left" Height="27" Margin="250,242,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="110" Text="{Binding Source={x:Static include:Communication.ipAddressServer}, Path=include:Communication.ipAddressServer, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="221,131,0,0" VerticalAlignment="Top" Height="47" Width="139" Click="Button_Click_1"/>
...
This is the beginning of the C# MainWindow Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using interactive_fountain.Include;
namespace interactive_fountain
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Trace.WriteLine("ip: " + Communication.ipAddressServer);
}
...
And this is the beginning of the class I want to do data binding with:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
namespace interactive_fountain.Include
{
public static class Communication
{
public static string ipAddressServer = "hello";
...
Whenever I try to do two-way data binding, the place holder "hello" doesn't appear anymore. When I write in the textBox and press the button, the output will always be ip: hello no matter what I write in the box. I have looked at a lot of threads regarding this issue but I did not find a solution that worked for me.
Does anyone know how I could make it work?
Thanks in advance!!
WPF data binding works on public properties only, your ipAddressServer is a static field (aka class variable) and not a property, so it won't be used. It's also failing at following proper naming conventions.
Your mess of a binding is the old style static binding, use {Binding Path=(w:Communication.IpAddressServer)} instead (after you fix #1, of course). w is the relevant XAML namespace definition.
Static properties don't have standard notifications for change, since static classes can't implement interfaces (for what I hope are obvious reasons). Instead WPF uses a convention-based approach of using a public static event PropertyChangedEventHandler StaticPropertyChanged and call that to notify changes. It's not clear if you want your property to be mutable, but you mentioned the change notification mechanism explicitly, so just throwing it out there.
I want to use embedded images in my portable code. I am using a markup extension as many different videos and guides have shown. My project compiles and runs but no image is displayed. These guides say to put the images under "references" but I am unable to drag an image there or right click and add one in so they are in a folder called Images. If the problem is that they aren't under references then how do I get them there? Otherwise if anyone can spot the error that would be much appreciated.
https://www.c-sharpcorner.com/article/add-images-icons-and-splash-screen-in-xamarin-forms/
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/images?tabs=vswin
About.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace SVCAPB
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class About : ContentPage
{
public About()
{
InitializeComponent();
Image embeddedImage = new Image { Source = ImageSource.FromResource("SVCAPB.Images.apbLeaders.jpg") };
}
}
}
About.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SVCAPB.MarkupExtensions"
x:Class="SVCAPB.About"
Title="About">
<ContentPage.Content>
<ScrollView>
<StackLayout
HorizontalOptions="Fill"
VerticalOptions="Fill"
BackgroundColor="#FFC107">
<Image Source="{local:EmbeddedImage ResourceId=SVCAPB.Images.apbLeaders.jpg }"></Image>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
EmbeddedImage.cs(under folder MarkupExtensions):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace SVCAPB.MarkupExtensions
{
public class EmbeddedImage : IMarkupExtension
{
public string ResourceId
{
get;
set;
}
public object ProvideValue(IServiceProvider serviceProvider)
{
if (String.IsNullOrWhiteSpace(ResourceId)) return null;
return ImageSource.FromResource(ResourceId);
}
}
}
Your code is correct, the problem is in the way of adding the images or the reference of your class
1.-Right click on your Images folder -> Add-> Add files-> select your image
2.- This step is necessary as it is marked in the documentation
-if you are using Xamarin studio right click on the image -> Build Action -> EmbeddedResource
-if you are using Visual studio right click -> properties -> Build Action -> EmbeddedResource
or
if you are using Xamarin studio you only need xmlns:local="clr-namespace:SVCAPB"
if you are using Visual studio you need to specify the directory xmlns:local="clr-namespace:SVCAPB.MarkupExtensions"
I'm attempting to bind a string property to a TextBox's Text field in XAML. I am doing this in a UserControl. I've searched StackOverflow and the internet in general and found various related topics, some examples:
Binding objects defined in code-behind
WPF: simple TextBox data binding
I've followed the code in these examples as best as I can but the Input property does not appear to be binding to the TextBox. I've tried various different methods of setting up the DataContext, including from the code behind and it's still not working.
What is it that I'm missing, is this an issue because it's a UserControl?
The code in the SearchInputTextBox_TextChanged event is called but always outputs an empty string. If I put a Debug.WriteLine call in the Input set section nothing happens.
The XAML file:
<UserControl x:Class="DatabaseViewerApp.View.SearchBox"
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="70" d:DesignWidth="240"
x:Name="Control">
<Border Padding="5" Background="#303030">
<StackPanel>
<TextBlock Text="Search" Margin="0,0,0,0" FontSize="20px" Foreground="White"></TextBlock>
<TextBox Name="SearchInputTextBox" Text="{Binding ElementName=Control, Path=Input}" Margin="0,5" FontSize="15px" TextChanged="SearchInputTextBox_TextChanged"></TextBox>
</StackPanel>
</Border>
</UserControl>
The C# file:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DatabaseViewerApp.View
{
/// <summary>
/// Interaction logic for SearchBox.xaml
/// </summary>
public partial class SearchBox : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string input;
public string Input
{
get { return input; }
set
{
if (value != input)
{
input = value;
NotifyPropertyChanged("Input");
}
}
}
public void NotifyPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public SearchBox()
{
InitializeComponent();
}
private void SearchInputTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
Debug.WriteLine(Input);
}
}
}
I think your problem is not that it isn't working... The issue is that you may not be testing it properly. Your code works for me in a new WPF solution. What you may be missing is that the Text binding gets updated when you leave the focus. In contrast, the TextChanged event gets fired as soon as the text is input into the text box.
So, whats happening is that when the TextChanged event is fired, the binding hasn't yet been updated. If you try putting a breakpoint in your property setter, then change some text in the text box, and move focus out of that control, you should see it get hit.
As an aside, there isn't much sense in binding your Text to a property in the code behind because the UI element can be accessed directly from there.
Try this:
<TextBox Name="SearchInputTextBox"
Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=UserControl},Path=Input}"
Margin="0,5" FontSize="15px" TextChanged="SearchInputTextBox_TextChanged">
</TextBox>
I created a sample custom control. It generates a dll after i build the project. Following is the code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace textbtn
{
public class CustomControl1 : Control
{
static CustomControl1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
}
}
}
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:textbtn">
<Style TargetType="{x:Type local:CustomControl1}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl1}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBlock Text="This is a Test" Foreground="Aqua" Background="AntiqueWhite"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
I am including this dll in another WPF application and wants to show this custom control when user clicks a button in the application. How do i do that ?
Following is the code in my WPF application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace TestCustomControls
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
textbtn.CustomControl1 cc = new textbtn.CustomControl1();
}
}
}
That strongly depends on what you mean by show. To just add it to the display:
AddChild(cc);
This adds it to the windows children group. This will probably blow up, since a window can only have one child. If you have a root grid called "ContentGrid", then it would be:
ContentGrid.Children.Add(cc);
The problem with both these approaches is that you don't control the position. You can set margin properties etc. to fix that of course. If your custom control were to inherit from Window (instead of control), you could do a show dialog if you want a dialog box:
cc.ShowDialog();
Of course, better than all these approaches would be to just show it in XAML instead of modifying the UI in code-behind :)
I have some controls where I set their Name property to unique names, but I am unable to access them in the matching C# code file.
I have tried:
this.ControlName
MainWindow.ControlName
ControlName
but it does "see" them.
How do I do this?
Also do I have to do something special for nested controls inside wrap panels, grid views, etc?
EDIT:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
namespace EditorWindow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow ( )
{
}
}
}
<Window x:Class="EditorWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Effects Editor">
<DockPanel>
<ListView x:Name="EffectsListView">
</ListView>
</DockPanel>
</Window>
For accessing any element in code behind you will need to set x:Name directive.
It tells the XAML parser to add a field representing the named element to the automatically generated portion of the Window class just like Winforms.
In a WPF application, there’s no requirement to name each and every element. You should name only those elements which you want to programatically interact with.
An example:
<TextBlock x:Name="tblText" Text="Stackoverflow rocks."></TextBlock>
EDIT:
I used the following code and I was able to access the list view:
namespace WpfApplicationUnleashed
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
EffectsListView.Width = 10;
}
}
}
<Window x:Class="WpfApplicationUnleashed.Window1"
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"
xmlns:local="clr-namespace:WpfApplicationUnleashed"
Title="Window1" >
<DockPanel>
<ListView x:Name="EffectsListView"></ListView>
</DockPanel>
</Window>
have you set their x:Name="ControlName" property in xaml?
Here is more information on x:Name directive.
For example:
<Button x:Name="Button1">Click Me</Button>