WPF - Global Properties and User Controls - c#

Greetings
I have a Main Window which will hold multiple User Controls. I will give you a better view with an example picture:
<!--Player 1-->
<local:ucRaces x:Name="ucRacesP1" Width="78" Height="33" Visibility="Hidden" />
<Image Name="imageRacePlayer1" Height="27" Width="27" />
<!--Player 2-->
<local:ucRaces x:Name="ucRacesP2" Width="78" Height="33" Visibility="Hidden" />
<Image Name="imageRacePlayer2" Height="27" Width="27" />
UC3 and UC4 are the same User Control
UC3 has been given the name ucRacesP1 (Hidden by default)
UC4 has been given the name ucRacesP2 (Hidden by default)
Depending on which button is pressed on the image one of these controls becomes visible.
Now what I want to do is, when a person selects a value in UC3 the properties for player1 need to be set. When a value gets selected in UC4 I need the properties for player2 to be set. I was thinking to do this with properties but when searching for Properties and WPF I stumbled upon Dependency Properties. Which started to confuse me a bit, would I need to use normal Properties or these Dependency Properties.
How can I know if I have to set the player1 values or the player2 values (this depends from which UserControl sends the data)?
How would I save these values best for the entire application?
Is putting the User Controls on hidden at the start (due to positioning) the best way or is there a better alternative?
Thank you for your time reading my question(s)!

i think , your statring point is
Depending on which button is pressed on the image one of these controls becomes visible
1- There are certain buttons on the image and user can click on the image.
2- You can make use of ICommand interface to exceute the specific command in UI i.e. if user press Palyer1 , you cna execute Player1Command if user presses Player2 , you can execute Player2Command.
3- There may be the duplication of code in player1 and player2 but don't worry about it , you can always refactor the code first thing is to dispatch the command to the respective command handler.

Related

WPF C# Button Binding and TextBox to Button Binding

I am fairly new to WPF and have two questions?
Question #1:
From my XAML snip below, by button "btnRed" word's fine with my code behind. When the button is clicked, the proper view is display. However, how does one perform the same thing "programmatically"? Hence, my next question.
Question #2:
I am not sure how to make a "textbox" and "button" work together to perform the same action. What I'm trying to do is this. (1) I would like the textbox to be linked to the "DataContext" of the button, "btnDisplayView". (2) so when I type in, say, "RedView" into the textbox and click the button, the correct view is displayed.
My long term goal is to have a database, with a couple of tables. A table for "MenuItems" and a table for "Views". Instead of using buttons, I'll use the menu control. Then once a menu item is selected, it would display the correct view.
But for now, I'm startings small and trying to keep it simple:
--------- WPF - XAML START ---------------------------
<StackPanel Grid.Column="0" Orientation="Vertical">
<TextBox x:Name="txtDisplayView" Height="23" Margin="5" TextAlignment="Center"/>
<Button x:Name="btnDisplayView" Content="Display" Margin="5" Click="btnDisplay_Click"/>
<Button x:Name="btnRed" Content="Red" Margin="5" DataContext="RedView" Click="Red_Click"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Vertical">
<ContentControl Margin="5" Content="{Binding}"/>
</StackPanel>
-----------WPF - XAML END -------------------------
If someone could show me how to get this to work, it would help me move my project in the right direction and would be greatly appreciated.
What you need here is:
Create a property in your DataContext that represents the selected item
Bind that property to your TextBox element
Now, you have two options. One is "WPF Friendly" and the other is more Windows Forms-ish:
Create a command (take a look at this article) that reads a parameter, which will be binded to the property you created before
On the Click event, you can read the binded property value
I personally prefer the first solution. Why? Because when you change it to a Menu, for example, your work will be only to populate the menu with your list items (the MenuItem class also has a Command property, so the implementation is the same as with a Button). You will only need to change the source!

Use SendKeys in a UserControl

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.

Change a section of a window upon click event

I have a treeview at the left side of the screen, and when I click on any of the TreeViewItem, I want the right side of the screen to change accordingly.
For example, clicking on 'Project' would display on the right half of the screen, a label for project name along with the project name in a text box, and a similar label-textbox pair for some other fields. Clicking on a sub-option of 'Project' such as 'Task 1' should change the right half of the screen such that instead of labels and textboxes for project name and details, it should now be for task name/details. Atm, I only care about label-textbox pairs but in the future I'll need some more sophisticated options, maybe buttons and tables.
What I thought of was to have a grid premade for each option, when I clicked on 'Project' there would be a grid which displays all the info for a Project. And when I then clicked on 'Task 1', the Project grid should be hidden and the Task grid should be displayed with the fields filled out.
Is this possible? What should I be using to create templates that I can then choose from?
Firoz already mentioned the important bit. A rough guess is that you're not using MVVM pattern, so to minimize the adaption effort, you could add a Content Control to your window and set the content of this control whenever a selection is made. You can put any User Control in there.
Using MVVM would mean you bind that Content Control to a property on your ViewModel (of type UIElement or UserControl) and set an instance whenever a bound selected values changes. Speaking of selected Value, I think the default TreeView is not really Binding-friendly, so you might end up with behaviours that do the binding for you.
What you are asking to do is quite easy and possible, but I don't think you are thinking quite big enough.
As your project grows and the number of different things that you want to show expands, then you are going to need to show and hide more and more controls. This is quite quickly going to get unmanageable. Instead think about some other controls deal with this, in some ways you are doing something very like a tabbed dialog, just with a hierarchical set of tabs.
A tabbed dialog has a panel and a set of tabs, when you click on each tab, the content of the panel changes. In fact you can create UserControls one for each specialised set of UI that you want to display, e.g. you could have a ProjectControl that displays all of your project textboxes, labels, buttons etc.
In addition WPF has this neat feature called DataTemplates, these define how a type of data should look when it is displayed. So if you where to have a
public class MyProject
{
public string Name {get;set;}
}
Then you could define
<DataTemplate DataType="{x:Type MyProject}>
<TextBox Text="{Binding Name}"/>
</DataTemplate>
And WPF will automatically convert the data into to its visual form if you set it as the content of the tab panel.
However this type of displaying content in a panel is not the only WPF control that does this. There is also something called a NavigationFrame, which also can be used wrapped into a Window as a NavigationWindow. This control provides you ways to navigate to the next Page to display. Pages can be just like the UserControls in a tabbed dialog, but can also be URIs, enabling you to link in content from the web if you wish. In addition you can call NavigateTo from other controls enabling you build much more usable interfaces.
I worked through the process of building a full windows control panel style interface in
http://alski.net/post/2012/01/11/WPF-Wizards.aspx
and http://alski.net/post/2012/01/13/WPF-Wizards-part-2-Glass.aspx
I've added later VS2012 style glows in
http://alski.net/post/2013/09/14/WPF-Re-creating-VS2012Office-2013-window-glow.aspx
And then released the entire source code as open source at
http://winchrome.codeplex.com/
This comes with support for embedding Navigation panels with
<WinChrome:SearchableNavigationWindow
x:Class="WinChrome.Win7Demo.MainWindow"
...
xmlns:WinChrome="clr-namespace:WinChrome;assembly=WinChrome"
Style="{StaticResource Win7NavigationWindow}">
<WinChrome:SearchableNavigationWindow.Navigation>
<view:Navigation x:Name="navigationTree"/>
</WinChrome:SearchableNavigationWindow.Navigation>
(Full source code)
Where the navigation window is embedded as, but can also be a TreeView.
<UserControl x:Class="WinChrome.View.Navigation" ...>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" Padding="12,0"
VerticalScrollBarVisibility="Auto" >
<StackPanel>
<Button
Margin="0,12,0,0" Style="{StaticResource LinkNavigatorButtonStyle}"
Content="Home"
Command="{Binding
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Win7Demo:MainWindow}, AncestorLevel=1},
Path=GoHomeCommand}" />
</StackPanel>
</ScrollViewer>
(Full source code)

Metro application directly focuses on my first field

I'm creating this test Metro application using Windows 8, VS2012, C# and XAML. There are different TextBox in the application page arranged in a StackPanel. When the application is launched the focus is on the first TextBox.
I was wondering how to "deactivate" this.
Here's a pic, as you can see the first field is focused (color changed and ToolTip displayed).
When your UI is loaded you can remove focus from the TextBox by applying a Programmatic focus state to any other control.
Imagine that you have a Button named myButton. You can:
myButton.Focus(FocusState.Programmatic);
You cannot however use FocusState.Unfocused state to remove focus from the TextBlock because it is not allowed and will throw an exception.
One simple fix for this is place something to catch it first with IsTabStop="True" with a 0 Opacity which is a bit hacky but the only way I know. So something like;
<TextBox IsTabStop="True" Opacity="0" Height="1" Width="1"/>
<!-- Then the rest of your content like your other TextBox stuff -->

How to stop an (InputScope = Number) textbox from disappearing when it gains focus?

I have searched for other answers, but none are clear enough.
I have a problem where whenever I click on a textbox that I set the InputScope to "number", the number pad comes up but the box I was typing in disappears..
Here is a screenshot and my code.
(I am also overriding the light/dark theme on windows phone to do it)
<TextBox InputScope="Number" Height="72" HorizontalAlignment="Left"
Margin="159,190,0,0" Name="aTextBox" VerticalAlignment="Top" Width="227"
TextChanged="aTextBox_TextChanged" Foreground="Black" BorderThickness="0"
Background="White" />
Your problem appears to be that there is a different visual state for when the TextBox has input focus, which matches the phone theme you're trying to override. If you want to fight against the system theme, you'll need to retemplate the TextBox.
In Blend, in the Objects and Timeline window, right-click on the TextBox and select Edit Template | Edit a Copy...
In the dialog that appears, name your new style / template and where you want to create it in the XAML. Click OK.
You are now in template edit mode. (If you want to exit this mode, click the Return scope button at the top of the Objects and Timeline window)
Click on the States tab (or go to Window | States if not visible) and you can see all the different visual states for each mode of the TextBox (focused, unfocused, etc). As you click on each one, you'll see the TextBox in the designer change. Select each state and change the colors to what you want them to be.
Specifically, note how in the Focused state, the TextBox background becomes transparent by default. This is your issue. Change it to what you want it to be.
Finally, I want to recommend that you don't try to override the Light / Dark theme on Windows Phone, unless you are replacing it outright with your own branding / color scheme. It's a lot of work and it could annoy and confuse users who are used to seeing the theme they have chosen.
Good luck!
Try like this:
<TextBox Text="NumericTextBox">
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="Number" />
</InputScope>
</TextBox.InputScope>

Categories