Click Event in Silverlight User Control - c#

I have user control in Silverlight which has a button click event. When I add that user control to a page, the click event does not fire. Is there something else I need to do?
Update
The user control by itself fires the click event. When inside the page, it does not
Page
<navigation:Page x:Class="RadControlsSilverlightApp2.Page1"
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="640" d:DesignHeight="480"
Title="Page1 Page" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:my1="clr-namespace:TestSilverLight.UserControls;assembly=TestSilverLight">
<Grid x:Name="LayoutRoot">
<sdk:Label Height="28" HorizontalAlignment="Left" Margin="101,38,0,0" Name="label1" VerticalAlignment="Top" Width="120" Content="Test page" />
<my1:Top10Programs HorizontalAlignment="Left" Margin="335,71,0,0" Name="top10Programs1" VerticalAlignment="Top" />
</Grid>
User control
<UserControl x:Class="RadControlsSilverlightApp2.MainPage"
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" BorderThickness="1" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">

Have you raised an event in the usercontrol that is handled in the main page?
UserControl XAML
<Grid x:Name="LayoutRoot" Background="White" Height="133">
<sdk:Label Height="18" HorizontalAlignment="Left" Margin="12,31,0,0" Name="label1" VerticalAlignment="Top" Width="58" Content="Name" />
<sdk:Label Content="Password" Height="18" HorizontalAlignment="Left" Margin="12,60,0,0" Name="label2" VerticalAlignment="Top" Width="58" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="89,27,0,0" Name="textBox1" VerticalAlignment="Top" Width="253" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="89,55,0,0" Name="textBox2" VerticalAlignment="Top" Width="253" />
<Button Content="Login" Height="23" HorizontalAlignment="Left" Margin="161,101,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
UserControl code behind
public class userNameEventArgs : EventArgs
{
public string userName{get;set;}
}
public partial class LoginBox : UserControl
{
public event EventHandler<userNameEventArgs> LoggedIn;
public LoginBox()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
LoggedIn(this, new userNameEventArgs(){userName=textBox1.Text});
}
}
Mainpage XAML
<Grid x:Name="LayoutRoot" Background="White">
<Button Content="Main Page" Height="23" HorizontalAlignment="Left" Margin="36,50,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<local:LoginBox Margin="100,122,179,223" LoggedIn="LoginBox_LoggedIn" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="36,376,0,0" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top" Width="94" />
</Grid>
Mainpage codebehind
public partial class MainPage : UserControl
{
public MainPage()
{
// Required to initialize variables
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Mainpage pressed!!");
}
private void LoginBox_LoggedIn(object sender, userNameEventArgs e)
{
textBlock1.Text = e.userName;
}
}
This allows the text block on the main page to be updated when the button on the user control is clicked. It raises an event that is handled on the mainpage. The EventArgs tranfers the information between the user control and the mainpage.
Hope this helps.

Related

Get data from another window

Project Informations
Windows Presentation Foundation Project
C# as programming language
Description
Is it possible to receive data from an user input in Window1 and show this input in MainWindow?
I will open the user input as a file from Window1 and will show the content of it in the RichTextBox of MainWindow.
Window1
<Window x:Name="window1" x:Class="Writer.Window1"
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:Writer"
mc:Ignorable="d"
Title="New" Height="130" Width="600" WindowStyle="None" WindowStartupLocation="CenterScreen" ResizeMode="CanMinimize">
<Grid Margin="0,0,0,-2">
<Rectangle HorizontalAlignment="Center" Height="30" Stroke="Black" VerticalAlignment="Top" Width="600" Fill="Black"/>
<Label Content="Open" HorizontalAlignment="Left" Margin="0,2,0,0" VerticalAlignment="Top" Foreground="White"/>
<Button Content="X" Margin="579,5,10,0" VerticalAlignment="Top" Background="Black" Foreground="White" BorderBrush="Black" ToolTip="Exit" Focusable="False" IsTabStop="False" Click="Button_Click"/>
<Label Content="Select the path" HorizontalAlignment="Left" Margin="0,35,0,0" VerticalAlignment="Top"/>
<TextBox HorizontalAlignment="Left" Margin="5,61,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" IsTabStop="False"/>
<Button Content="Select" HorizontalAlignment="Left" Margin="5,84,0,0" VerticalAlignment="Top" BorderBrush="White" Background="#FFADADAD" Width="45"/>
</Grid>
</Window>
MainWindow
<Window x:Name="MainWindow1" x:Class="Writer.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:Writer"
mc:Ignorable="d"
Title="Writer" Height="450" Width="800" WindowStyle="None" WindowStartupLocation="CenterScreen" ResizeMode="CanMinimize">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="164*"/>
<RowDefinition Height="83*"/>
<RowDefinition Height="203*"/>
</Grid.RowDefinitions>
<Rectangle HorizontalAlignment="Center" Height="30" Stroke="Black" VerticalAlignment="Top" Width="800" Fill="Black"/>
<Label Content="Writer" HorizontalAlignment="Left" Margin="0,2,0,0" VerticalAlignment="Top" Foreground="White"/>
<Button Content="_" HorizontalAlignment="Left" Margin="765,5,0,0" VerticalAlignment="Top" Background="Black" Foreground="White" BorderBrush="Black" Focusable="False" ToolTip="Minimize" IsTabStop="False" ClickMode="Press" Click="Button_Click_1"/>
<Button Content="X" Margin="779,5,10,0" VerticalAlignment="Top" Background="Black" Foreground="White" BorderBrush="Black" ToolTip="Exit" Focusable="False" IsTabStop="False" Click="Button_Click"/>
<Menu Margin="0,30,0,114" Height="20">
<MenuItem Header="File">
<MenuItem Header="New">
<MenuItem.Icon>
<Image Source="/file-added.svg"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Open" Click="MenuItem_Click"/>
<MenuItem Header="Open from server"/>
<MenuItem Header="Save"/>
<MenuItem Header="Save as"/>
<MenuItem Header="Close file"/>
<MenuItem Header="Close folder"/>
</MenuItem>
<MenuItem Header="Start">
<MenuItem Header="Font">
<MenuItem Header="Font"/>
<MenuItem Header="Family"/>
<MenuItem Header="Size"/>
</MenuItem>
<Separator/>
<MenuItem Header="Bold"/>
<MenuItem Header="Italic"/>
<MenuItem Header="Underline"/>
<MenuItem Header="Strikethrough"/>
</MenuItem>
<MenuItem Header="Insert">
<MenuItem Header="New site"/>
</MenuItem>
<MenuItem Header="Layout">
</MenuItem>
<MenuItem Header="View">
</MenuItem>
<MenuItem Header="Help"/>
</Menu>
<RichTextBox x:Name="RichTextBox1" Margin="0,50,0,0" BorderBrush="White" Cursor="Arrow" IsTabStop="False" Grid.RowSpan="3" FontFamily="Segoe UI" BorderThickness="0,0,0,0">
<FlowDocument>
<Paragraph>
<Run Text=""/>
</Paragraph>
</FlowDocument>
</RichTextBox>
</Grid>
</Window>
Yes, there is a way.
Implement a public method in Window1 that gives you the data.
Then use the reference to Window1 and call that method.
If MainWindow does not have a reference to Window1, give it the reference.
Here's an example. It assumes that you open the second window from within the main window.
In addition to the CC-BY-SA license of Stack Overflow, I license this as CC-0 for anyone who needs this code in one of his projects.
MainWindow.xaml
<Window x:Class="GetDataFromOtherWindow.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"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<Button Content="Open other window" Click="Button_Click" />
<Button Content="Get data from other window" Click="Button_Click_1" />
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace GetDataFromOtherWindow
{
public partial class MainWindow : Window
{
private Window1? otherWindow;
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
otherWindow = new Window1();
otherWindow.Show();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (otherWindow != null)
{
MessageBox.Show(otherWindow.GetData());
}
}
}
}
Window1.xaml
<Window x:Class="GetDataFromOtherWindow.Window1"
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"
Title="Window1" Height="141" Width="400">
<StackPanel>
<RichTextBox Name="richBox">
<FlowDocument>
<Paragraph>
<Run Text="This is some text"/>
</Paragraph>
</FlowDocument>
</RichTextBox>
</StackPanel>
</Window>
Window1.xaml.cs
using System.Windows;
using System.Windows.Documents;
namespace GetDataFromOtherWindow
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
public string GetData()
{
TextRange textRange = new TextRange(
richBox.Document.ContentStart,
richBox.Document.ContentEnd
);
return textRange.Text;
}
}
}
Note that this is not very MVVM-friendly, because this code has no model which would know about the business logic.
As per the comments, if you want to show the data after closing Window1, you can do this:
MainWindow.xaml.cs
using System.Windows;
namespace GetDataFromOtherWindow
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var otherWindow = new Window1();
otherWindow.ShowDialog();
MessageBox.Show(otherWindow.GetData());
}
}
}
Code for getting the data just before closing the window:
using System.Windows;
namespace GetDataFromOtherWindow
{
public partial class MainWindow : Window
{
private Window1? otherWindow;
public MainWindow()
{
InitializeComponent();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (otherWindow != null)
{
MessageBox.Show(otherWindow.GetData());
}
base.OnClosing(e);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
otherWindow = new Window1();
otherWindow.Show();
}
}
}

WPF Binding to a DependencyProperty problem with an custom User Control inside a Window

I need some help. I created a custom User Control, and inserted it into the Main Window. However, Im not able to bind a Property in the Window to a DependencyProperty in the User Control.
Here's the User Control code.
XAML:
<UserControl x:Class="SomeExample.UCFullName"
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"
xmlns:local="clr-namespace:SomeExample"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Margin="0,0,0,0" Orientation="Vertical" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<StackPanel Orientation="Vertical">
<Label BorderBrush="White" BorderThickness="1" Content="First Name :" FontSize="14" FontWeight="SemiBold" Foreground="White" Height="30" HorizontalAlignment="Left" Margin="0,2,0,0" VerticalAlignment="Top" Width="100"/>
</StackPanel>
<Grid>
<TextBox Name="FirstName" BorderBrush="Black" BorderThickness="1" FontSize="14" FontWeight="SemiBold" Height="30" HorizontalAlignment="Left" Margin="2,2,0,0" MaxLength="20" VerticalAlignment="Top" Width="100" TextChanged="TxtBlock_TextChanged"/>
</Grid>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<StackPanel Orientation="Vertical">
<Label BorderBrush="White" BorderThickness="1" Content="Last Name :" FontSize="14" FontWeight="SemiBold" Foreground="White" Height="30" HorizontalAlignment="Left" Margin="0,2,0,0" VerticalAlignment="Top" Width="100"/>
</StackPanel>
<Grid>
<TextBox Name="LastName" BorderBrush="Black" BorderThickness="1" FontSize="14" FontWeight="SemiBold" Height="30" HorizontalAlignment="Left" Margin="2,2,0,0" MaxLength="20" VerticalAlignment="Top" Width="100" TextChanged="TxtBlock_TextChanged"/>
</Grid>
</StackPanel>
</StackPanel>
And here's the code behind
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace SomeExample
{
public partial class UCFullName : UserControl, INotifyPropertyChanged
{
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected void Notify(string propertyName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion INotifyPropertyChanged implementation
public string ValueFullName
{
get { return (string)GetValue(ValueFullNameProperty); }
set
{
SetValue(ValueFullNameProperty, value);
Notify("ValueFullName");
}
}
// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueFullNameProperty =
DependencyProperty.Register("ValueFullName", typeof(string), typeof(UCFullName), new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public UCFullName()
{
InitializeComponent();
}
private void TxtBlock_TextChanged(object sender, TextChangedEventArgs e)
{
ValueFullName = FirstName.Text + " " + LastName.Text;
}
}
}
This is how it looks:
And here's the code of the Main Window:
<Window x:Class="SomeExample.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:SomeExample"
mc:Ignorable="d"
Title="Some Example" Height="200" Width="400">
<StackPanel Margin="0,0,0,0" Orientation="Vertical" Name="SpManual" Background="Black">
<GroupBox Header="Name" Foreground="White" FontSize="14" Name="groupBoxCoordinateStart" >
<local:UCFullName ValueFullName="{Binding Path = PropertyFullName, Mode = TwoWay, RelativeSource={RelativeSource AncestorType=UserControl}}"></local:UCFullName>
</GroupBox>
<StackPanel Name="SpBtnInsert" Orientation="Horizontal" HorizontalAlignment="Center" Visibility="Visible">
<Button Name="btnShowFullName" BorderBrush="White" BorderThickness="1" FontSize="14" FontWeight="SemiBold" Height="30" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="2,2,0,0" Background="Transparent" Content="Show Name" Foreground="White" Width="98" Click="BtnShowFullName_Click"></Button>
</StackPanel>
</StackPanel>
And the code behind:
using System.Windows;
namespace SomeExample
{
/// <summary>
/// Lógica de interacción para MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public string PropertyFullName { get; set; }
public MainWindow()
{
InitializeComponent();
}
private void BtnShowFullName_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Current full name :" + PropertyFullName);
}
}
}
And of course, I expected that when I pressed the button, I got a message with the full name entered by the user. However, I got nothing.
Edit: Here's the solution to the problem, for people who visit this page with a similar problem.
<local:UCFullName ValueFullName="{Binding Path = PropertyFullName, RelativeSource={RelativeSource AncestorType=Window}}"></local:UCFullName>
You are binding to the wrong AncestorType. Instead of UserControl the type must be Window. Window extends Control but not UserControl.
<local:UCFullName ValueFullName="{Binding Path=PropertyFullName, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=Window}}" />
Also because you set the Binding.Mode to TwoWay, the binding source PropertyFullName must be able to notify the binding target ValueFullName about value changes. To achieve this, you need to implement PropertyFullName as a DependencyProperty to enable two way binding.
As a a side note:
The following code can be problematic
public string ValueFullName
{
get { return (string)GetValue(ValueFullNameProperty); }
set
{
SetValue(ValueFullNameProperty, value);
Notify("ValueFullName"); // This line might never get called
}
}
This is just a CLR wrapper for the actual DependencyProperty and will never be invoked by the framework. When using the binding on this property the wrapper will never get called and therefore the event will never get raised.
As BionicCode has pointed out, you can change the AncestorType. Another option is to set DataContext of the Window.
You can either do it in the constructor
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
or in the XAML.
<Window DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}">
This way you don't have to specify source in your bindings (as long as you bind to code-behind properties).

How to fix sending data from new instance of form to datagrid on Main Form

I had this simple inventory manager in WPF using a datagrid hooked up to a table using SQL working the other day but changed a line of the code and now it's broken. I've slept since I broke it and can't work out how to fix it again.
The problem seems to be with with dataGrid1.Items.Add(testtables) from the MainWindow class below.
I ran it in a trycatch with the exception message saying that the operation is not valid while ItemsSource is in use, and that ItemsControl.ItemsSource should be used to access and modify elements instead.
Here's the code for the main form
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
DataClasses1DataContext dc = new DataClasses1DataContext(Properties.Settings.Default.TestingConnectionString);
public MainWindow()
{
InitializeComponent();
if (dc.DatabaseExists())
{
dataGrid1.ItemsSource = dc.TestTables;
}
}
private void newButton_Click(object sender, RoutedEventArgs e)
{
Window1 window1 = new Window1();
window1.Show();
}
public void NewLine (int ID, string nm, decimal pc)
{
TestTable testtable = new TestTable
{
ID = ID,
Name = nm,
Price = pc
};
dataGrid1.Items.Add(testtable);
}
private void saveButton_Click_1(object sender, RoutedEventArgs e)
{
dc.SubmitChanges();
}
}
}
XAML code for MainWindow
<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>
<Button x:Name="newBtn" Content="New" HorizontalAlignment="Left" Margin="217,62,0,0" VerticalAlignment="Top" Width="75" Click="newButton_Click"/>
<Button x:Name="save" Content="Save" HorizontalAlignment="Left" Margin="401,82,0,0" VerticalAlignment="Top" Width="75" Click="saveButton_Click_1"/>
<DataGrid x:Name="dataGrid1" HorizontalAlignment="Left" Height="100" Margin="77,236,0,0" VerticalAlignment="Top" Width="575" IsReadOnly="True"/>
</Grid>
</Window>
and here's the code for the secondary form that asks the user to input the data
public partial class Window1 : Window
{
public int iDNumber;
public string name;
public decimal price;
public Window1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
iDNumber = Convert.ToInt32(iDTextBox.Text);
name = Convert.ToString(nameTextBox.Text);
price = Convert.ToDecimal(priceTextBox.Text);
((MainWindow)Application.Current.MainWindow).NewLine(iDNumber, name, price);
this.Close();
}
}
XAML code for Window1
<Window x:Class="WpfApp2.Window1"
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="Window1" Height="450" Width="400">
<Grid Margin="0,0,0,0">
<Button Content="Save" HorizontalAlignment="Left" Margin="156,362,0,0" VerticalAlignment="Top" Width="76" Click="Button_Click"/>
<TextBox x:Name="iDTextBox" HorizontalAlignment="Left" Height="23" Margin="156,79,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="nameTextBox" HorizontalAlignment="Left" Height="23" Margin="156,117,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="priceTextBox" HorizontalAlignment="Left" Height="23" Margin="156,155,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Label Content="ID" HorizontalAlignment="Left" Margin="95,79,0,0" VerticalAlignment="Top"/>
<Label Content="Name" HorizontalAlignment="Left" Margin="95,117,0,0" VerticalAlignment="Top"/>
<Label Content="Price" HorizontalAlignment="Left" Margin="95,155,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
When it was working the other day, it nicely added the new line of data to the SQL database (however didn't automatically show the updated info in the application, but this isn't the problem at the moment).
In this section of your code:
public MainWindow()
{
InitializeComponent();
if (dc.DatabaseExists())
{
dataGrid1.ItemsSource = dc.TestTables;
}
}
You are displaying the data by assigning the datatable to the datagrid.ItemsSource property. If you do this, you need to add items by modifying the DataTable instead of the DataGrid.
dataGrid1.Items.Add(testtable);
So instead of what's above, try adding the testtable item to your existing collection dc.TestTables

Accessing classes instantiated during MainWindow() constructor

I'm pretty new to C# and WPF and I'm having a bit of trouble accessing a class that was instantiated during the MainWindow() constructor.
Here's my code:
namespace PivotBlockPicker.View
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
WrenchViewModel wrench = new WrenchViewModel();
MeasurementViewModel measurements = new MeasurementViewModel();
}
private void modelSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
wrench.GetWrench(modelSelector.SelectedItem);
}
}
}
And here's my XAML:
<Window x:Class="PivotBlockPicker.View.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:PivotBlockPicker.View"
xmlns:vm="clr-namespace:PivotBlockPicker.ViewModel"
xmlns:m="clr-namespace:PivotBlockPicker.Model"
mc:Ignorable="d"
Title="MainWindow" Height="347" Width="288.666"
DataContext="vm:WrenchViewModel">
<Grid>
<GroupBox x:Name="wrenchBox" Header="Torque Wrench" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="262" Width="250">
<Grid>
<Grid Margin="0,0,0,140.667" Height="88" VerticalAlignment="Bottom">
<TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="10,3,0,0" TextWrapping="Wrap" Text="Model:" VerticalAlignment="Top"/>
<ComboBox x:Name="modelSelector" HorizontalAlignment="Left" Margin="52,0,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="modelSelector_SelectionChanged">
<ComboBoxItem>QD2R200</ComboBoxItem>
<ComboBoxItem>QD2R50</ComboBoxItem>
</ComboBox>
<Grid HorizontalAlignment="Left" Width="228" Margin="0,27,0,0">
<TextBlock x:Name="blockFirstTP" Text="TextBlock" HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
<TextBlock x:Name="blockSecondTP" Text="TextBlock" HorizontalAlignment="Left" Margin="10,21,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
<TextBlock x:Name="blockThirdTP" Text="TextBlock" HorizontalAlignment="Left" Margin="10,42,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
</Grid>
</Grid>
<GroupBox x:Name="blockBox" Header="Pivot Block Dimensions" HorizontalAlignment="Left" Margin="10,100,0,0" VerticalAlignment="Top" Height="86">
<Grid>
<TextBlock x:Name="blockTextHorizontal" HorizontalAlignment="Left" Margin="51,12,0,0" TextWrapping="Wrap" Text="Vertical" VerticalAlignment="Top" Height="16" Width="40"/>
<TextBox x:Name="blockHorizontal" Text="" HorizontalAlignment="Left" Height="20" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="36" MaxLength="5"/>
<TextBlock x:Name="blockTextVertical" HorizontalAlignment="Left" Margin="51,37,0,0" TextWrapping="Wrap" Text="Horizontal" VerticalAlignment="Top" Height="16" Width="58"/>
<TextBox x:Name="blockVertical" Text="" HorizontalAlignment="Left" Height="20" Margin="10,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="36" MaxLength="5"/>
</Grid>
</GroupBox>
</Grid>
</GroupBox>
<Button x:Name="button" Content="Get Wrench Info" HorizontalAlignment="Left" Margin="185,277,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
My window has a ComboBox that, when the selection is changed, I want to call a function from the WrenchViewModel class that will populate some variables (that I will later databind to the TextBlocks.
However, my call to wrench.GetWrench results in a "The name wrench does not exist in the current context" build error.
Floating my mouse cursor over the the instance of "wrench" in the MainWindow constructor shows that it's a local variable.
How can I get this to be accessible to at least the MainWindow class?
You can move the variable declaration one scope up into the class, so it's available not only inside the constructor (local scope) but in the whole class:
public partial class MainWindow : Window
{
private WrenchViewModel wrench;
private MeasurementViewModel measurements;
public MainWindow()
{
InitializeComponent();
wrench = new WrenchViewModel();
measurements = new MeasurementViewModel();
}
private void modelSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
wrench.GetWrench(modelSelector.SelectedItem);
}
}
The curly brackets brackets in C# denote scope, the tell you where a method, class, namespace, or other scopes end. You cannot access anything outside it's own scope, or from another scope.
What you need to do is move the declaration of your variable outside the scope of the constructor. You still assign your view model in side the constructor, but the declaration is in a scope that the other method can see.
Like so:
public partial class MainWindow : Window
{
WrenchViewModel wrench;
public MainWindow()
{
InitializeComponent();
wrench = new WrenchViewModel();
Because you have defined a local variable:
public MainWindow()
{
InitializeComponent();
WrenchViewModel wrench = new WrenchViewModel();
MeasurementViewModel measurements = new MeasurementViewModel();
}
Inside of constructor.
You should change it to this private member:
public partial class MainWindow : Window
{
private WrenchViewModel _wrench = new WrenchViewModel();
private MeasurementViewModel _measurements = new MeasurementViewModel();
public MainWindow()
{
InitializeComponent();
}
private void modelSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
_wrench.GetWrench(modelSelector.SelectedItem);
}
}

WPF Data binding with ResourceDictionary MVVM

I'm trying to bind a View with a ViewModel within ResourceDictionary but it does not work.
The application is very simple window with 2 textboxes. When I type text to textbox1, atutomatically, textbox2 must get the same text. Of course my textboxes from the View have to be binded to my properties in ViewModel.
I'm new to WPF and the way I started to bind Views and ViewModels was in the codebehind of a View:
DataContext = new MyViewModel();
Now I'm trying to achieve a cleaner separation. My code is
App.xaml:
<Application x:Class="NavigationCleanBinding.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="/Views/MainWindowView.xaml">
<Application.Resources>
<ResourceDictionary Source="MainResourceDictionary.xaml" />
</Application.Resources>
</Application>
MainResourceDictionary.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xamlpresentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Views="clr-namespace:NavigationCleanBinding.Views"
xmlns:ViewModels="clr-namespace:NavigationCleanBinding.ViewModels">
<DataTemplate DataType="{x:Type ViewModels:MainWindowViewModel}">
<Views:MainWindowView />
</DataTemplate>
</ResourceDictionary>
MainWindowView.xaml:
<Window x:Class="NavigationCleanBinding.Views.MainWindowView"
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>
<TextBox Height="23" HorizontalAlignment="Left" Margin="61,14,0,0"
Name="textBox1" VerticalAlignment="Top" Width="120"
Text="{Binding TestData, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="Test:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="label1" VerticalAlignment="Top" Width="43" />
<Label Content="Result:" Height="28" HorizontalAlignment="Left" Margin="10,46,0,0"
Name="label2" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="61,48,0,0"
Name="textBox2" VerticalAlignment="Top" Width="120"
Text="{Binding TestData, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
MainWindowViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NavigationCleanBinding.ViewModels
{
class MainWindowViewModel
{
private String _testData;
public String TestData
{
get { return _testData; }
set { _testData = value; }
}
private MainWindowViewModel()
{
_testData = null;
}
}
}
UPDATE:
I changed property TestData to this:
public String TestData
{
get { return _testData; }
set
{
_testData = value;
OnPropertyChanged("TestData");
}
}
And implemened the INotifyPropertyChanged like this:
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
so user1064519 was on the right track:
the View needs to be a UserControl, not a Window, as it is hosted in the MainWindow
the ViewModel needs to be loaded into the MainWindow, this is what triggers the DataTemplate to be discovered and loaded.
<Window x:Class="WpfTemplateBootstrap.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfTemplateBootstrap"
Title="MainWindow" Height="350" Width="525">
<ContentControl>
<ContentControl.Content>
<local:MainWindowViewModel />
</ContentControl.Content>
</ContentControl>
After that you should be up and running.
I have posted an in-depth example here: wpf bootstrapping datatemplates--the chicken and the egg
DataTemplate sholudnt contain window, it can contains any kind of control.
DataTemplate :
<DataTemplate DataType="{x:Type ViewModels:MainWindowViewModel}">
<Views:MainWindowView />
</DataTemplate>
UserControl :
<UserControl x:Class="NavigationCleanBinding.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525">
<Grid>
<TextBox Height="23" HorizontalAlignment="Left" Margin="61,14,0,0"
Name="textBox1" VerticalAlignment="Top" Width="120"
Text="{Binding TestData, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="Test:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="label1" VerticalAlignment="Top" Width="43" />
<Label Content="Result:" Height="28" HorizontalAlignment="Left" Margin="10,46,0,0"
Name="label2" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="61,48,0,0"
Name="textBox2" VerticalAlignment="Top" Width="120"
Text="{Binding TestData, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</UserControl>
Window :
<Window x:Class="NavigationCleanBinding.Views.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<ContentControl Content={Binding}/>
</Window>
Your ViewModel must implement the interface INotifyPropertyChanged and raise a PropertyChanged event when any binded property value changes, so that your view can know that changes ocurred.

Categories

Resources