How to reach and-, name own FrameworkElement from xaml - c#

I have the following, working code:
<Window x:Class="GemTowerDefense.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:GemTowerDefense"
mc:Ignorable="d"
Title="Gem Tower Defense" Height="670" Width="800"
Loaded="Window_Loaded">
<Window.Resources>
<local:GameControl x:Key="MyGameControl"/>
</Window.Resources>
<Grid>
<Border Background="Gray" Height="600" Width="600" Margin="3,26,189,3">
<local:GameControl/>
</Border>
</Grid>
</Window>
Here you can see that I have the "local:GameControl" duplicated. This is because I only had the GameControl inside the "Grid" and the "Border". Everything worked fine, I implemented OnRender inside GameControl, it draws out everything I want it to.
My problem is, that I want this local:GameControl to interact with the MainWindow's buttons:
<Button Click="Life_Button_Click" Content="Buy 1 Life" HorizontalAlignment="Left" Margin="608,26,0,0" VerticalAlignment="Top" Width="170"/>
<Button Click="Upgrade_Button_Click" Content="Upgrade Chances" HorizontalAlignment="Left" Margin="608,51,0,0" VerticalAlignment="Top" Width="170"/>
<Button Click="Place_Button_Click" Content="Place Gems" HorizontalAlignment="Left" Margin="608,156,0,0" VerticalAlignment="Top" Width="170"/>
So I added this inside "Grid". But inside the Button Click Event Handlers, I don't know how to reach GameControl.
What I want to do is something like this:
public partial class MainWindow : Window
{
GameControl control { get; set; }
private void Life_Button_Click(object sender, RoutedEventArgs e)
{
control.BuyLife();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
control = Application.Current.MainWindow.Resources["MyGameControl"] as GameControl;
}
}
How can I achieve this to work?
This doesn't work obviously, because I cannot name GameControl with an x:Key, only if I add it as a resource, but then I dont know how to refer to it as a FrameworkElement in the xaml code.

Give the control an x:Name:
<Border Background="Gray" Height="600" Width="600" Margin="3,26,189,3">
<local:GameControl x:Name="control" />
</Border>
You can then access it in the code-behind:
private void Life_Button_Click(object sender, RoutedEventArgs e)
{
control.BuyLife();
}

Related

WPF How to raise the mouse event on two UIElement overlaid to each other

I have two UIElements. An Image inside a ViewBox and Canvas that overlays it. On both is registered MoseMove event in the code behind.
Currently is raised the event only on the element that is on the top.
Is there any way how to raise MouseMove on both UIElements?
XAML:
<Window x:Class="WpfApp2.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:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid ClipToBounds="True">
<Viewbox Name="border" StretchDirection="Both" Stretch="Uniform" Panel.ZIndex="0" >
<Grid>
<Image Name="image" Panel.ZIndex="1" >
<Image.Source>
<BitmapImage UriSource="d:\test.png"/>
</Image.Source>
</Image>
</Grid>
</Viewbox>
<Canvas Name="canvas" Panel.ZIndex="2" Background="Transparent" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Grid>
</Window>
Code-behind:
using System.Windows;
using System.Windows.Input;
namespace WpfApp2
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
border.PreviewMouseMove += Border_PreviewMouseMove;
canvas.PreviewMouseMove += Canvas_PreviewMouseMove;
}
private void Border_PreviewMouseMove(object sender, MouseEventArgs e)
{
//Not Raised...
}
private void Canvas_PreviewMouseMove(object sender, MouseEventArgs e)
{
//Raised...
}
}
}
You can try this :)
private void Canvas_PreviewMouseMove(object sender, MouseEventArgs e)
{
border.RaiseEvent(e);
}

Focus Textbox across multiple Usercontrols controlling from MainWindow

i have two usercontrols which is bound in MainWindow. What i want when MainWindow is Loaded, textbox1 which is in usercontrol1 should be focused automatically, and when i hit down arrow from keyboard textbox2 which is in usercontrol2 should be focused. And again on up arrow focus textbox1.
Below is MainWindow's xaml code`
<Window x:Class="FocusTextboxesFromMain.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:FocusTextboxesFromMain" Loaded="Window_Loaded"
mc:Ignorable="d"
Title="Focus Textboxes Testing" Height="450" Width="800">
<Grid>
<StackPanel>
<local:UserControl1/>
<local:UserControl2/>
</StackPanel>
</Grid>
Below is Usercontrol1's xaml code`
<UserControl
x:Class="FocusTextboxesFromMain.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:local="clr-namespace:FocusTextboxesFromMain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Width="800"
Height="200"
mc:Ignorable="d">
<Grid Background="Red">
<TextBlock
FontSize="50"
Foreground="White"
Text="UserControl1" />
<TextBox
x:Name="textbox1"
Width="200"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="25" />
</Grid>
and below is Usercontrol2's xaml code`
<UserControl
x:Class="FocusTextboxesFromMain.UserControl2"
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:local="clr-namespace:FocusTextboxesFromMain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Width="800"
Height="200"
mc:Ignorable="d">
<Grid Background="Green">
<TextBlock
FontSize="50"
Foreground="White"
Text="UserControl2" />
<TextBox
x:Name="textbox2"
Width="200"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="25" />
</Grid>
please note that i want all my logic in MainWindow Class, MvvM should not be involved
namespace FocusTextboxesFromMain
{
using System.Windows;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Focus textbox1 of usercontrol1
}
// on down arrow then Focus textbox2 of usercontrol2
// and again on up arrow then Focus textbox1 of usercontrol1
}
}
sorry for bad explanation, thanks in advance
You can find what you are looking for in the answer of this question:
Moving to next control on Enter keypress in WPF
Just follow the code and create related event
public MainWindow()
{
InitializeComponent();
this.PreviewKeyDown += new KeyEventHandler(txtFirst_KeyDown);
this.PreviewKeyDown += new KeyEventHandler(txtSecond_KeyDown);
}
private void txtFirst_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Down)
{
txtSecond.Focus();
}
}
private void txtSecond_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Up)
{
txtFirst.Focus();
}
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
txtFirst.Focus();
}

ShowDialog() can be bypassed?

I accidentally found this while working with my project, but I was able to reproduce this in a base project:
I open a MainWindow, then with ShowDialog a child window, Owner set to the Main. When I click on the Main, the Child starts to flash, then I start clicking between the Main and the Child very fast, and sometimes the Main gets the focus, then I able to open another Child window.
MainWindow:
<Window x:Class="WpfShowDialog.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="300" WindowStartupLocation="CenterScreen" >
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" >
<TextBlock Text="MainWindow" Margin="10" />
<Button Content="Open child" Margin="10" Click="Button_Click" />
</StackPanel>
</Window>
Code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var childWindow = new ChildWindow()
{
Owner = this
};
childWindow.ShowDialog();
}
}
ChildWindow:
<Window x:Class="WpfShowDialog.ChildWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ChildWindow" Height="150" Width="200" WindowStartupLocation="CenterOwner">
<Grid>
<TextBlock Text="ChildWindow" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Window>
Code behind:
public partial class ChildWindow : Window
{
public ChildWindow()
{
InitializeComponent();
}
}
I click on between these red circles:
Is this some kind of bug, or I miss something?

Page navigation in Silverlight Gadget?

I have been working with Silverlight gadget, but when I create a new page, I can't navigate to the new page; the navigate does not exist.
code
public partial class Test
{
public Test()
{
MessageBox.Show("af");
InitializeComponent();
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
private void button1_Click(object sender, RoutedEventArgs e)
{
}
}
and xaml code is
<navigation:Page x:Class="SilverlightGadgetDocked.Test"
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:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="359" d:DesignHeight="225"
Title="Test Page">
<Grid x:Name="LayoutRoot">
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="182,103,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
</navigation:Page>

How can I bind a ListBox control to a List in WPF?

I want to create a 2 way bind between a listbox and a .NET list.
In my GUI, I have a listbox, a textbox and add and remove buttons.
The listbox displays cars, and my goal is to create a two-way bind between the .Net car list and the listbox: when the user enters a car into the textbox, it gets updated only in the .Net list, and the listbox is updated automatically.
When the user press the GUI "remove" button, a car gets removed from the GUI and the .Net list is updated automatically.
I've started to write the xaml code, but figured that I don't actually know how to do the binding on both sides (c# and xaml):
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="369" Loaded="Window_Loaded">
<Window.Resources>
<ObjectDataProvider x:Key="carsData"
ObjectType="{x:Type c:Window1}" />
</Window.Resources>
<Grid Width="332">
<ListBox Margin="10,62,0,100" Name="myListBox" HorizontalAlignment="Left" Width="120" ItemsSource="{Binding Source={StaticResource CarsData}}"/>
<Button Height="23" Margin="66,0,0,65" Name="addBtn" VerticalAlignment="Bottom" Click="addBtn_Click" HorizontalAlignment="Left" Width="64">add</Button>
<TextBox Margin="10,0,0,64.48" Name="myTextBox" Height="23" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="47" />
<Button Height="23" Margin="66,0,0,33" Name="removeButton" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="64" Click="removeButton_Click">Remove</Button>
</Grid>
</Window>
There is my c# code:
public partial class Window1 : Window
{
MyModel listMgr;
ObservableCollection<Car> carList;
public Window1()
{
InitializeComponent();
listMgr = new MyModel();
}
private void addBtn_Click(object sender, RoutedEventArgs e)
{
listMgr.add(new Car(0, myTextBox.Text, 2011));
}
private void removeButton_Click(object sender, RoutedEventArgs e)
{
//myListBox.Items.RemoveAt(0);
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
carList = listMgr.getList();
myListBox.DataContext = carList;
//secondListBox.DataContext = carList;
}
}
This is a quick version, you'll need to add code to check the car is selected, etc.
To see your Car data you'll need to define a data template. In the example it's just a simple name, but you can change the text colour, font size, add more fields, etc.
It's best to work on the list when adding / removing cars, not on the ListBox directly.
XAML:
<Window x:Class="cars.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="car_template" DataType="Car">
<TextBlock Text="{Binding name}"/>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ListBox x:Name="cars_box" Margin="5" ItemsSource="{Binding}" ItemTemplate="{StaticResource car_template}"/>
<TextBox x:Name="new_car_box" Margin="5"/>
<Button Content="add" Click="add_car" Margin="5"/>
<Button Content="delete" Click="delete_car" Margin="5"/>
</StackPanel>
C#:
using System.Collections.ObjectModel;
using System.Windows;
public partial class MainWindow : Window
{
ObservableCollection<Car> cars = new ObservableCollection<Car>();
public MainWindow()
{
InitializeComponent();
cars.Add(new Car("Volvo"));
cars.Add(new Car("Ferrari"));
cars_box.DataContext = cars;
}
private void add_car(object sender, RoutedEventArgs e)
{
cars.Add(new Car(new_car_box.Text));
}
private void delete_car(object sender, RoutedEventArgs e)
{
cars.Remove((cars_box.SelectedItem as Car));
}
}
public class Car
{
public string name { get; set; }
public Car(string _name)
{
this.name = _name;
}
}

Categories