HOPEFULLY, someone strong in WPF knows what's going on... The scenario I've sampled below is also applicable to others too, like textbox, command buttons, etc...
I'm playing with creating custom user controls... Ex: working with a simple Combobox. In one project class library LibA I've created some samples derived from... ex: TextBox, ComboBox, Window, etc. A second library LibB I'm creating another class derived from ex: Combobox in LibA... Otherwise, no problem.... done similar thing in C# WinForms with no problems.
Now, the problem, I drag the control (from LibB) onto the first "Window" (native so no derivation issues) of the app, save and run. The derived library doesn't even hit its constructor which I just put a simple command just test it was getting created properly worked or not, but its not... In the XAML of the form, it is properly referencing both namespace projects, so I know that appears correct.
So, I then created a derived combobox in the same original LibA, put that on the form, and IT properly went into the constructor.
Here's a snippet of what I have going on.
namespace LibA
{
public class MyCombo1 : ComboBox
{
public MyCombo1()
{ ToolTip = "this is my base declaration"; }
}
public class MyCombo1b : MyCombo1
{
public MyCombo1b() : base()
{ ToolTip = "this constructor IS reached"; }
}
}
In a separate project (library),
using FirstLibraryThatHas_MyCombo1
namespace LibB
{
public class OtherLibCombobox : MyCombo1
{
public OtherLibCombobox() : base()
{ ToolTip = "this version is NOT being recognized in the window"; }
}
}
So, neither of these are visually designed, they are all in code only... In addition, I've done it with the TextBox control too, same results... It doesn't stop in the debugger... Any ideas?
Although I've changed actual names from sample, here's a brand new window, one with original class declaration AND one with the DERIVED version.. Here's a full XAML test window
<Window x:Class="MyProject.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300"
xmlns:my="clr-namespace:WPFGUI;assembly=WPFGUI"
xmlns:my1="clr-namespace:DerivedControls;assembly=DerivedControls">
<Grid>
<my:MyComboBoxClass
Name="MyComboBoxInWindow"
HorizontalAlignment="Left"
Height="23"
Width="120" />
<my1:cboDerivedComboClass
Name="cboDerivedComboInWindow"
Height="23"
HorizontalAlignment="Left"
Width="120" />
</Grid>
</Window>
Isn't this making a circular reference?
You call MyDerivedControl that is in another assembly, and DerivedControl needs the primary assembly
because it inherits a type you defined there.
And then, you try to display it in a window from the primary assembly?
Try to clean and rebuild your project.
I've tried and failed to reproduce the problem. I think you have a different problem, though. If you use the xaml above - the number two combobox will completely cover the first - thus you will not be able to get the tooltip...
Also, check that all assemblies target the same framework version.
Related
UPDATE * My error had to do with the computer I was using and not being part of a FIPS validated algorithm. That error only appeared after I closed Visual Studio and tried to compile the default blank WPF form. I did the exact same thing on a personal computer and it compiled as expected. *
I'm familiar with creating windows form using C#. I looked into methods to change the look of my forms, similar to using skins, and was told that it would be easier if I I used WPF....ok.
In an effort to become familiar with WPF, I picked up a book, "MASTERING_WINDOWS_PRESENTATION_FOUNDATION" and it was slow moving with a discussion on MVVM and data binding (new topics to me). I felt the I could learn the difference between WPF and Windows Forms much faster if I first tried to create a simple WPF application. Then, as I read, I could see how something done in a very familiar way using Windows Forms, is done using WPF.
Unfortunately, I'm stuck right out the box!
Using VS2017, I created a new WPF App (.NET Framework) I then added a text box and a button. I created a name for both as this does not appear to be automatically created like with Windows Forms. I then double click on the button and a method block is created in the MainWindow.xaml.cs file. I proceed to add text to the textbox
(txtbox_1.Text="Hello;").
I noticed a few things:
1.) The InitializeComponent(); call in the MainWindow() method is underlined and corresponds to the CS0103 Error
2.) Intellisense did not recognize the textbox. I typed out the full name and it created an error when I was done. (Same CS0103 Error)
I looked through stackoverflow but found articles about Xamarin. I've heard of this as a way to write code for Android but do not know how it relates to what I'm trying to do.
What am I missing?
Here is my XAML file:
<Window x:Class="WpfApp4.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:WpfApp4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button x:Name="btn_browse" Content="Button" HorizontalAlignment="Left" Margin="524,91,0,0" VerticalAlignment="Top" Width="75"/>
<TextBlock x:Name="txtbox_1" HorizontalAlignment="Left" Margin="134,93,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="20" Width="363"/>
</Grid>
</Window>
And here is my MainWindow.xaml.cs file:
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void SimpleMethod()
{
txtbox_1.Text = "Hello";
}
}
}
That InitializeComponent(); line is hugely significant since it is that instruction makes your xaml turn into UI.
If it's underlined then your partial class for code behind isn't matching up with the xaml.
You will have something like
Either that or you're missing some fundamental references should have been added when you started your project.
I suggest you just bin your sln though.
Just delete it and start again.
Create a new wpf project.
Hit f5.
If it crashes and burns your VS install is broken.
Anyone and everyone will tell you to learn MVVM. And you should.
https://social.technet.microsoft.com/wiki/contents/articles/31915.wpf-mvvm-step-by-step-1.aspx?Redirected=true
https://social.technet.microsoft.com/wiki/contents/articles/32164.wpf-mvvm-step-by-step-2.aspx?Redirected=true
That means that your MainWindow class actually does not inherit from System.Windows.Window class.
I don't see a reference to System.Windows in your class. This is the namespace, where the WPF Window basic class is defined. So your Window base class can reference a Window class from some other namespace, and, that's why it has no InitializeComponents() method and can not reference the property from XAML. Try first adding this using directive to code behind class. If that doesn't do the task, check if your project has a reference to System.Windows. If there is no System.Windows in your reference manager (this could be if your project is set to compile in .NET 4.0) add references to PresentationFramework, PresentationCore and WindowsBase.
The error had to do with the work computer I was using ... something to do with FIPS. You should be able to create a new WPF project and compile the blank form without error. I did the exact same thing on a personal computer and it compiled as expected. I was also able to reproduce a WinForms project as a WPF using code behind without error. Implementation using MVVM took a significant amount of time since the concept of view models was new to me but, in the end, it's not bad.
I want to use the C# System.Windows.Forms.SendKeys.SendWait() Method to send Keystrokes from an OnScreenKeyboard to a Textbox. Since I may use this OnScreenKeyboard at other places too I created a UserControl with View (for the Design of the Keyboard) and Viewmodel (basically for calling the Sendkeys.SendWait() Method) in an extra project.
Within this project I created a MainView where I included the UserControl via a ContentControl as you can see in the Code below. CurrentPage basically refers to the Viewmodel of the Keyboard.
<Window.Resources>
<DataTemplate DataType="{x:Type viewModel:KeyboardViewmodel}">
<view:KeyboardView/>
</DataTemplate>
</Window.Resources>
<Grid>
<Border Background="White">
<HeaderedContentControl Content="{Binding Path=CurrentPage}"/>
</Border>
<TextBox Width="120"/>
</Grid>
I now have the OnScreenKeyboard and a Textbox in my Window. Clicking into the Textbox and pressing buttons of my OnScreenKeyboard will result in text appearing in my Textbox. All Controls within the KeyboardView are set to avoid getting focus. This is necessary to maintain focus on the Textbox.
The Buttons in the KeyboardView all bind to the Command ClickCommandin my KeyboardViewmodel. Here is the code of the KeyboardViewmodel:
public class KeyboardViewmodel : BaseModel
{
public BaseCommand ClickCommand { get; set; }
public KeyboardViewmodel()
{
ClickCommand = new BaseCommand(PressAndRelease);
}
public void PressAndRelease(object key)
{
if (((string)key).Length <= 1)
SendKeys.SendWait((string)key);
else
SendKeys.SendWait("{" + (string)key + "}");
}
}
Now I did create a NuGet Package with these Files and imported them to the project where I want to use my OnScreenKeyboard.
I did do basically the same as when I tested the OnScreenKeyboard before.
But let me explain the structure of the project a little more:
I have a MainView + MainViewmodel. The MainViewmodel manages the navigation between available pages. To show these pages I have - as in the short example before - a ContentControl whose content is bound to a CurrentPage Property. The MainViewis a normal Window, all other Views are UserControls.
In one of these pages I need an OnScreenKeyboard (DetailsView + DetailsViewmodel). So it seemed logical to me to use another ContentControl within the DetailsView:
<Border Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="3" Height="Auto" Width="Auto">
<ContentControl Content="{Binding Path=OnScreenKeyboard}"/>
</Border>
I create the KeyboardViewmodel in the constructor of the DetailsViewmodel. The constructor of the DetailsViewmodel is called in the MainViewmodel at startup.
So now everything works out fine so far, the OnScreenKeyboard is shown on the correct page in the correct place. If I click a button of the OnScreenKeyboard the proper bound command is called and the SendKeys.SendWait() Method is called.
But no text appears in the TextBox. I have a very bad understanding of the SendKeys.SendAwait() Method. Also, the MSDN Documentation seems to be not very exhaustive on this topic.
It states: "Sends the given keys to the active application, and then waits for the messages to be processed."
Now. The Active / Focused Application is my Application. So my guess is that the KeyStrokes should be processed by my Textbox.
My Questions:
Any guesses how to debug the 'SenWait()' Method further e.g. track where the strokes are really sent to or something like that?
Is this the correct way for sending KeyStrokes to an active Application? It seems like SendKeys comes from Windows Forms, I use WPF.
Should I just pass my Textbox as reference to the OnScreenKeyboard and write directly to the referenced Textbox? This would make me much less flexible in regards of reusability.
Update:
As pointed out in the comments this could probably be a duplicate question.
I am well aware of the various different solutions and have already considerd them:
http://wpfkb.codeplex.com/
http://www.codeproject.com/Articles/32568/A-Touch-Screen-Keyboard-Control-in-WPF
http://www.codeproject.com/Articles/145579/A-Software-Virtual-Keyboard-for-Your-WPF-Apps
But as one may understand these projects are looking all way too powerfull for my simple needs.
Here a screenshot to provide a better understanding of my needs:
It is really as simple as that. 4 rows of buttons that will never change, no other controls / functionality than sending the CommandParameter of the pressed button to the Textbox / Active Form.
Researching on that specific problem hasn't shown any problems like that. In most other SO Questions the problem is to send Data to another Window, not to send Data WITHIN the current Window.
So I don't consider this question as duplicate.
i have some UserControls that are shown fine in designer, but i can't make any changes to the design-time example content from the constructor. It seems like it is not executed at all.
XAML:
<UserControl x:Class="Example.Test"
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>
<TextBlock Name="testx" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
</Grid>
Code:
using System.ComponentModel;
using System.Windows.Controls;
namespace Example
{
/// <summary>
/// Interaction logic for Test.xaml
/// </summary>
public partial class Test : UserControl
{
public Test()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(this))
testx.Text = " IN DESIGN!";
}
}
}
I've tried many options, but still can't get it how to display design-time data in WPF designer :( Different context binding also shows nothing...
PS: Tried clean VS2012 and VS2013 projects on Win8. NOTHING WORKS! :( I don't know what to do, haven't found anything similar on the net... Is it sufficient to just add design check in constructor and set existent control text? It should work, right?
K, the short answer is: You're on the right path.
The long one is: It's a bit more complicated than that.
Your example will "kinda" work, as in, if you'll put an else testx.Text = RUNTIME; after your if, like that:
if (DesignerProperties.GetIsInDesignMode(this))
testx.Text= " IN DESIGN!";
else
testx.Text= " Runtime";
you'll see what you want on runtime, but you're design time will stay empty.
For the Design time, you also need to set the context if I'm not mistaken.
If you're using any of the MVVM framework out there, you kinda get this functionality for "free". As in, you'll have a "in design time" property and you can set whatever data you want for the design. The catch is that you need to have an empty constructor if my memory serves me right.
You'll also use bindings, and not set the text property directly.
I remember that the default WPF and binding for design time was lacking a bit last time I tried to do something like that in "vanilla" wpf (as in, no MVVM, no bindings), but I believe that with a bit of a hack it's achievable. Again, can't remember it from the top of my head.
I have a RootViewModel class, and I want to access an UI element (instantialized in MainWindow) from there. For that I set the class this way:
class RootViewModel : MainWindow, INotifyPropertyChanged
But the application doesn't start. It compiles and throws no error but the Window doesn't appear. If I remove that MainWindow, I can't access my element that has been created in MainWindow.xaml. What can I do to solve this?
EDIT: Ok, I understand that I shouldn't be doing that, it's going against what it is MVVM. But is there a way to modify directly something from MainWindow? What should I try instead of this?
Consider changing RootViewModel to a UserControl. Give it a DependencyProperty called Element, of type UIElement.
Add RootViewModel to the XAML for MainWindow and bind to the element you want to use, like this;
<RootViewModel Element="{Binding ElementName=SourceElement}"/>
WPF windows are objects, so you can always instantiate them manually, like so:
var foo = new FooWindow(); // new Window object
foo.Show(); // show window as non-blocking "dialog"
If you do that, you have access to any public or protected members of the window - that includes any child controls, as long as their Accessibility properties are marked accordingly. So, if FooWindow had a TextBox named txtFooName, you could access it like so:
string name = foo.txtFooName.Text // get string value from textbox
You can also assign to any public/protected members:
foo.txtFooName.Text = "Fizz Buzz, Inc.";
Now, MainWindow is generally set as the StartupUri of the application (in App.xaml), which makes it the entry point for the application, so I'm not entirely sure what you're trying to do.
I was able to achieve what I wanted by creating a
public ObservableCollection<ChartPlotter> myPlotCollection { get; set; }
And then adding a ChartPlotter there, and setting in XAML:
<DockPanel Grid.Column="2">
<ItemsControl Width="Auto"
Height="Auto"
ItemsSource="{Binding myPlotCollection}">
</ItemsControl>
</DockPanel>
So this way I have complete control over what is happening in myPlotCollection[0]. At this moment it's enough for me, later I'll give it another try to bind it properly.
I am trying to allow several classes to inherit a more general Silverlight user control to avoid redundancy in my code. The classes inherit the extended control, which then inherits the User Control class. The issue I have been running into is that the ExtendedControlExtension.g.cs file regenerates every time I compile, with the incorrect inheritance (it inherits User Control not my Extended Control).
Note that I have been inheriting the Extended Control in the .cs and g.cs files, but continuing to use the User Control tag in the .aspx file as this causes the error
Error 29 The tag 'ExtendedControl' does not exist in XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'.
Is there a way to fix this?
Thanks!
You cannot change the .g.cs file, in fact is says so right in the file. Also, it's unfortunate to use the term "custom control" as this means something specific and not what you are trying to do. But, the good news is that what you are trying to do is possible.
Derive from UserControl:
public class FancyUserControl : UserControl
{
// Your added common functionality.
}
and then add a new UserControl to your project using the normal mechanism, let's say UserControl1. Then edit the UserControl.xaml files as follows:
<local:FancyUserControl x:Class="SilverlightApplication1.UserControl1"
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:SilverlightApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
</Grid>
</local:FancyUserControl>
paying special attention to the three lines with local in them, adjusting to your application. Then edit the UserControl1.xaml.cs file as follows:
public partial class UserControl1 : FancyUserControl
{
public UserControl1()
{
InitializeComponent();
}
}
and Visual Studio won't be quite happy yet but finally rebuild your project and all will be well.
The class UserControl1 is now derived from FancyUserControl instead of UserControl and you can begin adding your common functionality. To add more controls you will need to manually edit the XAML and code-behind once after initially adding each new control to the project.