wpf how to change a canvas image Position programmatically - wpf

I am a student on my final year and im doing a project regarding WPF but i'm totally new to WPF and i have been assigned some tasks,but im currently stuck on how to change the Image position on the canvas programitically from left to right.below are the codes
<<Window x:Class="changing_bird_position.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Canvas Name="canvas" Background="LightBlue" Width="500" Height="280" Margin="264,0,28,0">
<Image Source="inlandbird.png" Name="Image" Height="43" Canvas.Left="55" Canvas.Top="22"/>
</Canvas>
<Button Content="Button" Click="Button_Click" Width="50" Height="50" Margin="246,0"/>
</StackPanel>
Xaml.cs
public partial class MainWindow : Window
{
Image img = new Image();
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Canvas.SetLeft(img, 200.0);
Canvas.SetTop(img, 200.0);

In your code behind you don't need to create this instance of an Image (img). You can access the image by it's name property.
I renamed the image in the xaml to make it clear.
XAML:
<Window x:Class="WpfApplication15.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Canvas Name="canvas" Background="LightBlue" Width="500" Height="280" Margin="264,0,28,0">
<Image Source="inlandbird.png" Name="BirdImage" Height="43" Canvas.Left="55" Canvas.Top="22"/>
</Canvas>
<Button Content="Button" Click="Button_Click" Width="50" Height="50" Margin="246,0"/>
</StackPanel>
</Window>
Code behind:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Canvas.SetLeft(BirdImage, 200.0);
Canvas.SetTop(BirdImage, 200.0);
}
}
}

Related

Invoking a WPF view (UserControl) method from the main window (Window)

I have a button on a view (UserControl) that invokes a method in the code-behind file. I would like to get rid of the button and instead, invoke the method from a menu item. Not sure how to do this. Here is some simple code illustrating this situation:
MainWindow.xaml (MainView is embedded):
<Window x:Class="Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:View="clr-namespace:Example.View"
Title="MainWindow" Height="600" Width="800" Background="Green">
<Grid>
<StackPanel>
<Menu>
<MenuItem Header="File" Click="MenuItem_Click">
</MenuItem>
</Menu>
<View:MainView/>
</StackPanel>
</Grid>
MainWindow.xaml.cs
using System.Windows;
namespace Example
{
public partial class MainWindow : Window
{
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("MainWindow");
// how can I invoke MainView methods like DoWork from here?
}
}
}
MainView.xaml
<UserControl x:Class="Example.View.MainView"
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" d:DesignHeight="500" d:DesignWidth="600">
<Grid Background="Yellow">
<Button HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10" Content="Show" Click="Button_Click"/>
</Grid>
</UserControl>
MainView.xaml.cs
using System.Windows.Controls;
namespace Example.View
{
public partial class MainView : UserControl
{
public MainView()
{
InitializeComponent();
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
DoWork();
}
public void DoWork()
{
MessageBox.Show("MainView");
}
}
}
You could just give a name to the MainView,
<Window x:Class="Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:View="clr-namespace:Example.View"
Title="MainWindow" Height="600" Width="800" Background="Green">
<Grid>
<StackPanel>
<Menu>
<MenuItem Header="File" Click="MenuItem_Click"/>
</Menu>
<View:MainView x:Name="mainView"/>
</StackPanel>
</Grid>
</Window>
and call the Method like this:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
mainView.DoWork();
}

Binding text property of text box to variable defined on MainWindow-WPF

I'm newbie on WPF and I have text box and button which open folder browser dialog.
When the user select folder I would like text box will contain the selected path.
So on MainWindow I added two variables:
public partial class MainWindow : Window
{
public string outputFolderPath { get; set; }
string reducedModelFolderPath { get; set; }
}
and when user selected folder path (after open folder dialog) I updated those variables by doing (for example):
outputFolderPath = dialog.SelectedPath
In MainWindow.xaml:
<TextBox x:Name="outputFolder" Width ="200" Height="30" Grid.Row="1" Grid.Column="1" Margin="5 10">
How can I bind TextBox.Text to outputFolderPath variable?
Thanks for your assitance!
You need to set DataContext of your window to this, to access your property in XAML, and after that bind to the property. As you are binding not to DependencyProperty, you should notify your binding that property has changed, which could be done by implementing INotifyPropertyChanged interface in your Window.
I've provided sample code to show the concept.
But this is very ugly, much better to use MVVM pattern instead.
MainWindow.xaml.cs
public partial class MainWindow : Window, INotifyPropertyChanged
{
public string outputFolderPath { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public event PropertyChangedEventHandler PropertyChanged;
private void Button_Click(object sender, RoutedEventArgs e)
{
outputFolderPath = "Some data";
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(outputFolderPath)));
}
}
MainWindow.xaml
<Window x:Class="simplest.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:simplest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Button Click="Button_Click" Content="Go" />
<TextBox x:Name="outputFolder" Width ="200" Height="30" Grid.Row="1" Grid.Column="1" Margin="5 10" Text="{Binding outputFolderPath}"/>
</Grid>
</Window>

How to programmatically set UserControl to Topmost?

How to programmatically set UserControl to Topmost of pc screen. I have multiple usercontrol in my wpf application, when I resize any usercontrol, I want to show this usercontrol top of the screen.
i want to show this usercontrol top of the screen.
If by that you mean "top of the screen" inside your application, then that is achieved by using Panel's ZIndex attached property.
Xaml :
<Grid x:Name="LayoutRoot">
<UserControl x:Name="TopMostUserControl"
Margin="10,140,106,48"
Panel.ZIndex="1"
Background="Green" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Panel.ZIndex="0"
Background="red" />
</Grid>
C# :
public MainWindow()
{
InitializeComponent();
Panel.SetZIndex(TopMostUserControl, 1);
Panel.SetZIndex(SecondUserControl, 0);
}
<Grid x:Name="LayoutRoot">
<UserControl x:Name="TopMostUserControl"
Margin="10,140,106,48"
Background="Green" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Background="red" />
</Grid>
Result :
However, if you mean to topmost that UserControl on the entire screen, then that would be something different, you should create another Window that hosts your topmost UserControl and you should change its TopMost property to true when you resize your other UserControls.
MainWindow :
<Grid x:Name="LayoutRoot">
<UserControl x:Name="FirstUserControl"
Margin="10,140,106,48"
Background="Green"
MouseDown="FirstUserControl_OnMouseDown" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Background="red" />
</Grid>
Code Behind :
public partial class MainWindow : Window
{
public TopMostWindow TopMostWindow;
public MainWindow()
{
InitializeComponent();
TopMostWindow = new TopMostWindow();
TopMostWindow.Show();
}
private void FirstUserControl_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
TopMostWindow.Topmost = true;
}
private void MainWindow_OnContentRendered(object sender, EventArgs e)
{
FirstUserControl.SizeChanged += FirstUserControl_OnSizeChanged;
SecondUserControl.SizeChanged += FirstUserControl_OnSizeChanged;
}
//This is to simulate the resizing
private void FirstUserControl_OnMouseDown(object sender, MouseButtonEventArgs e)
{
FirstUserControl.Width = 400;
}
}
TopMostWindow :
<Window x:Class="MvvmLight1.TopMostWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TopMostWindow"
Width="300"
Height="300"
Topmost="False"
WindowStyle="None">
<Grid>
<UserControl x:Name="TopMostUserControl" Background="Blue" />
</Grid>
</Window>
It depends in which container you are using it. Or in what scenario. Basically in Grid you just need to specify it as a last element under Grid container. Otherwise use Panel.ZIndex="1" on the UserControl declaration in XAML

How to call a window using tabcontrol in wpf

I have a Main_window which runs as base.
It has some buttons on its left side.
If button1 is clicked, I need a window ( which is defined separately as login) to open as a Tabcontrol in my Main_window (located at center).
So each time when I click one of the buttons, the corresponding windows should be shown as tabs in the main window.
Hoping for the right answer...
Thank You.
Try this
XAML:
<Window x:Class="Test1.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">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="134*" />
<ColumnDefinition Width="369*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Button Content="Login" Height="23" HorizontalAlignment="Left" Margin="24,28,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
<Grid Grid.Column="1">
<TabControl Name="TabControl"/>
</Grid>
</Grid>
</Window>
C#:
namespace Test1
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
TabItem item = new TabItem();
item.Header = "Some header";
//item.Content = < your content>
TabControl.Items.Add(item);
}
}
}

Binding to a property of a borders child

I have implemented my own simple version of a navigation window, mainly because navigation windows journal does not give me control over how many children can exist. So I am using a border inside a window and changig its child everytime. As children I am using a UserControl. I want to bind the title of my Window to the Title property of my current child. Somehow I cannot figure out a way to do it.
MainWindow XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="525"
Height="350"
Background="AliceBlue"
Title="{Binding Path=Child.Title,
ElementName=borderContent}">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="<-" x:Name="btnBack" />
<Button Content="->" x:Name="btnForward" />
</StackPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Content="1" Click="Button_Click_1" />
<Button Content="2" Click="Button_Click_2" />
</StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Border x:Name="borderContent" />
</ScrollViewer>
</DockPanel>
MainWindow Code behind:
using System;
using System.Windows;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("Title 1");
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("TITLE 2");
}
}
}
UserControl XAML:
<UserControl x:Class="WpfApplication1.ContentPage"
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 Text="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Title}" />
</Grid>
User Control Code behind:
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Content.xaml
/// </summary>
public partial class ContentPage : UserControl
{
public string Title
{
get { return (string)this.GetValue(ContentPage.TitleProperty); }
set { this.SetValue(ContentPage.TitleProperty, value); }
}
// Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(ContentPage), new UIPropertyMetadata(string.Empty));
public ContentPage(string Title)
{
this.Title = Title;
InitializeComponent();
}
}
}
Somehow the binding inside the UserControl is also not working. What am I doing wrong?
The problem is that the Child property of a Borderisn't a DependencyProperty so there is no change notification. You'll have to update the Binding manually everytime you change the Child
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("Title 1");
UpdateTitleBindingExpression();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
this.borderContent.Child = new ContentPage("TITLE 2");
UpdateTitleBindingExpression();
}
private void UpdateTitleBindingExpression()
{
BindingExpressionBase beb = BindingOperations.GetBindingExpressionBase(this, Window.TitleProperty);
if (beb != null)
{
beb.UpdateTarget();
}
}
I'm not sure why you are doing what you are doing, but regarding your question:
change "Source" to "RelativeSource"
<Grid>
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=Title}" />
</Grid>
That should fix the binding issue
Edit:
When you really want to do it that way, you could make the borderContent element an ContentControl and use the Content property instead. Since this is an DependencyProperty you're binding will work:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="525"
Height="350"
Background="AliceBlue"
Title="{Binding Content.Title, ElementName=borderContent}">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="<-" x:Name="btnBack" />
<Button Content="->" x:Name="btnForward" />
</StackPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Content="1" Click="Button_Click_1" />
<Button Content="2" Click="Button_Click_2" />
</StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ContentControl x:Name="borderContent" />
</ScrollViewer>
</DockPanel>
</Window>

Resources