UserControl Data Binding retrieve value - c#

with this simple code:
MainWindows:
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace itemcontrole_lesson
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public class TodoItem
{
public string Username { get; set; }
public int Completion { get; set; }
}
public partial class MainWindow : Window
{
List<TodoItem> items = new List<TodoItem>();
public MainWindow()
{
InitializeComponent();
items.Add(new TodoItem() { Username = "Eric", Completion = 45 });
items.Add(new TodoItem() { Username = "Maxwell", Completion = 80 });
items.Add(new TodoItem() { Username = "Sarah", Completion = 60 });
icTodoList.ItemsSource = items;
}
}
Mainwindows XAML:
<Window x:Class="itemcontrole_lesson.MainWindow"
xmlns:local="clr-namespace:itemcontrole_lesson"
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>
<ItemsControl x:Name="icTodoList">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:UserControl1}">
<local:UserControl1 />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
then a simple UserControle:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace itemcontrole_lesson
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
//String CurentUserName = ????????
//Int Progress = ????????
}
private void Button_Click(object sender, RoutedEventArgs e)
{
///hows to remove the user from items in main windows??
}
}
}
UserControle XAML
<UserControl x:Class="itemcontrole_lesson.UserControl1"
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="54.181" Width="399.331">
<Grid Margin="0,0,-155,0">
<Label Content="{Binding Username}" HorizontalAlignment="Left" Margin="23,23,0,0" VerticalAlignment="Top"/>
<Button Content="Close this UC" HorizontalAlignment="Left" Margin="414,22,0,0" VerticalAlignment="Top" Width="119" Click="Button_Click"/>
<ProgressBar HorizontalAlignment="Left" Value="{Binding Completion}" Height="10" Margin="204,23,0,0" VerticalAlignment="Top" Width="154"/>
</Grid>
</UserControl>
Pressing F5 everything will bind ok if you test.
But! how I'm supposed to retrieve my variable value in my usercontrole code?
see where I put comment in UC.
1- I need at least to find a way to remove this control from UI and from Items list?.
2-I'd like access username in my control and set it into a var
any suggestion?

Solution 1:
Use Tag property of button like below:
<Button Content="Close this UC" HorizontalAlignment="Left" Margin="414,22,0,0"
VerticalAlignment="Top" Width="119" Click="Button_Click" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
Event handler:
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
List<object> list = (button.Tag as ItemsControl).ItemsSource.OfType<TodoItem>().ToList<object>();
list.Remove(button.DataContext);
(button.Tag as ItemsControl).ItemsSource = list;
}
Solution 2:
More elegant solution:
Create this Style in your MainWindow:
<Window.Resources>
<Style TargetType="Button">
<EventSetter Event="Click" Handler="Button_Click"/>
</Style>
</Window.Resources>
So now the Handler of any Button Click event is in the MainWindow.xaml.cs.
Then change handler definition like below:
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
items.Remove(button.DataContext as TodoItem);
icTodoList.ItemsSource = null;
icTodoList.ItemsSource = items;
}

Related

WPF - Bind between two CheckBoxes' Content with a Label.Content in two different windows

I have two windows in my project(MainWindow and one small window for some properties of controls of the MainWindow). In one Tab in the MainWindow there is a Grid divided to ten Columns. In each Column there are some Controls. Below is a sample code of my project.
I want if I check the Period(CheckBox in PropertiesWindow) the Label(MainWindow) to be "Period" and when I check the Frequency(CheckBox in PropertiesWindow) the Label(MainWindow) to be "Frequency".
I want, when I check one of the checkboxes at the PropertiesWindow (Period or Frequency), the Label (lb_freq1) at the MainWindow to change its Content according to the Content of the checked CheckBox. (Moreover, the selected units to be displayed at the time_div1(Label)).
FIRST SOLUTION:
XAML MainWindow:
<Window x:Class="wpf1.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-wpf1"
mc:Ignorable="d"
Title="wpf1" Height="720" Width="1280" WindowStartupLocation="CenterScreen" Icon="kkk.bmp" Background="#FFE0E0E0" Foreground="#FF49A81D" BorderBrush="#FFB93838" >
<Grid>
<TabControl x:Name="tabControl">
<TabItem Header="Tab1">
<Grid>
<StackPanel>
<Label x:Name="lb_freq1" Content="Period" HorizontalAlignment="Center" Margin="0,10,0,0" />
<StackPanel Orientation="Horizontal" Margin="0" HorizontalAlignment="Center">
<TextBox x:Name="txt_freq1" Width="50" Height="20" HorizontalContentAlignment="Right" BorderThickness="1,1,0,1" HorizontalAlignment="Left" VerticalContentAlignment="Center"/>
<Label x:Name="time_div1" Content="us" Width="20" BorderThickness="0,1,1,1" Margin="0" HorizontalAlignment="Right" Height="20" Padding="0" BorderBrush="#FFABADB3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
</StackPanel>
<Label x:Name="lb_width1" Content="Pulse Width" HorizontalAlignment="Center" Margin="0,10,0,0" />
<StackPanel Orientation="Horizontal" Margin="0" HorizontalAlignment="Center">
<TextBox x:Name="txt_width1" Width="50" Height="20" HorizontalContentAlignment="Right" BorderThickness="1,1,0,1" HorizontalAlignment="Left"/>
<Label x:Name="pv_div1" Content="us" Width="20" BorderThickness="0,1,1,1" Margin="0" HorizontalAlignment="Right" Height="20" Padding="0" BorderBrush="#FFABADB3" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
</StackPanel>
<Button x:Name="Properties1" Content="Properties" Margin="10,30,10,10" HorizontalAlignment="Center" BorderBrush="Blue" Click="Properties1_Click" />
</StackPanel>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>
EDITED
Code Behind MainWindow:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Globalization;
using System.ComponentModel;
namespace wpf1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ViewModel viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Properties1_Click(object sender, RoutedEventArgs e)
{
string res1 = lb_freq1.Content.ToString();
string res3 = time_div1.Content.ToString();
var newWindow = new PWMProperties();
newWindow.Owner = this;
newWindow.ShowDialog();
string result1 = newWindow.Value1;
if (result1 == null)
{
lb_freq1.Content = res1;
}
else
{
lb_freq1.Content = result1;
}
string result3 = newWindow.Unit1;
if (result3 == null)
{
time_div1.Content = res3;
}
else
{
time_div1.Content = result3;
}
}
}
}
XAML PropertiesWindow:
<Window x:Class="wpf1.PWMProperties"
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:wpf1"
mc:Ignorable="d"
Title="Properties" Height="335" Width="285" ResizeMode="NoResize" BorderThickness="0" WindowStartupLocation="CenterOwner">
<Window.Resources>
<local:BoolConverter2 x:Key="Converter"></local:BoolConverter2>
<local:BoolConverter x:Key="Reverse"></local:BoolConverter>
</Window.Resources>
<Grid>
<StackPanel VerticalAlignment="Top" Margin="0,10,0,0" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<StackPanel Margin="0,0,49,0">
<RadioButton x:Name="SelectPeriod" Content="Period" Margin="0,0,0,0" Click="SelectPeriod_Click" />
<ComboBox x:Name="PeriodUnits" Padding="3,2,2,2" IsReadOnly="True" IsEditable="True" Text="us" IsEnabled="{Binding ElementName=SelectPeriod, Path=IsChecked}" SelectionChanged="PeriodUnits_SelectionChanged"
ItemsSource="{Binding PeriodComboBoxItems}">
</ComboBox>
</StackPanel>
<StackPanel Margin="20,0,0,0">
<RadioButton x:Name="SelectFrequency" Content="Frequency" Click="SelectFrequency_Click" />
<ComboBox x:Name="FrequencyUnits" Padding="3,2,2,2" IsReadOnly="True" IsEditable="True" Text="Hz" IsEnabled="{Binding ElementName=SelectFrequency, Path=IsChecked}" SelectionChanged="FrequencyUnits_SelectionChanged"
ItemsSource="{Binding FrequencyComboBoxItems}">
</ComboBox>
</StackPanel>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Margin="0">
<Button x:Name="OkButton" Content="OK" Margin="135,5,10,5" Click="OkButton_Click" Width="60" />
<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="60" Margin="0,5,10,5" />
</StackPanel>
</Grid>
</Window>
EDITED
Code Behind PropertiesWindow:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using System.IO;
using System.Xml;
using System.Windows.Markup;
namespace wpf1
{
/// <summary>
/// Interaction logic for Analog.xaml
/// </summary>
public partial class PWMProperties : Window
{
public ObservableCollection<string> PeriodComboBoxItems { get; set; }
public ObservableCollection<string> FrequencyComboBoxItems { get; set; }
public ObservableCollection<string> PulseWidthComboBoxItems { get; set;}
public PWMProperties()
{
InitializeComponent();
this.DataContext = this;
this.PeriodComboBoxItems = new ObservableCollection<string>() { "us", "ms", "s" };
this.FrequencyComboBoxItems = new ObservableCollection<string>() { "Hz", "kHz", "MHz" };
this.PulseWidthComboBoxItems = new ObservableCollection<string>() { "us", "ms", "s" };
}
string val1, val2, unit1, unit2;
private void OkButton_Click(object sender, RoutedEventArgs e)
{
if (SelectPeriod.IsChecked == true)
{
val1 = "Period";
if (unit1 == null || unit1!="ms") unit1 = "us";
}
if (SelectFrequency.IsChecked == true)
{
val1 = "Frequency";
if (unit1 == null || unit1!="kHz") unit1 = "Hz";
}
DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
}
public string Value1 { get { return val1; } }
public string Value2 { get { return val2; } }
public string Unit1 { get { return unit1; } }
public string Unit2 { get { return unit2; } }
private void PeriodUnits_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
unit1 = PeriodUnits.SelectedItem.ToString();
}
private void FrequencyUnits_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
unit1 = FrequencyUnits.SelectedItem.ToString();
}
}
public class BoolConverter2 : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool v = (bool)value;
return v;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotSupportedException();
}
}
}
Second possible solution:
Then, I've added to my MainWindow code a ViewModel:
public class ViewModel : INotifyPropertyChanged
{
private string _value1 = "Period";
public event PropertyChangedEventHandler PropertyChanged;
public string Value1
{
get { return _value1; }
set
{
_value1 = value;
OnPropertyChanged("Value1");
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
So, most of the code behind of the PropertiesWindow is deleted and I use Binding for the change of lb_freq1(Label) at the MainWindow.
<Label x:Name="lb_freq1" Content="{Binding Value1, Mode=TwoWay}" HorizontalAlignment="Center" Margin="0,10,0,0" />
I don't know how to continue from that state. I'm new to WPF and C#, and I would be thankful if someone could help me in any way.
MAIN ISSUE
I've edited my first solution, so if someone could take a look. What I managed to do now is almost what i want. But, there is a problem. I want, when I click on the OK.Button, the "settings" I made at Properties.Window should change the Labels at MainWindow. Although, when I click on the Cancel.Button or the Close.Button at the upper right corner, any changes made at the Properties.Window should not change the Labels at MainWindow.
Moreover, when I close the Properties.Window, and then open it again for a second time, the CheckBoxes and ComboBox.SelectedItems need to have the same state they had when the Properties.Window closed. But that doesn't happen.
You should set the DataContext of the two windows properly. Currently, you are setting and overriding it in multiple places. Here is my suggestions:
Use ElementName in your Binding in your windows, i.e., wpf1.PWMProperties and wpf1.MainWindow, whenever you want to Bind to a property in them. In other words, give them a name and Bind to them. For example:
<Window x:Class="wpf1.PWMProperties"
.....
Name="owner">
.....
<StackPanel Margin="0,0,49,0">
.....
ItemsSource="{Binding Path=PeriodComboBoxItems, ElementName=owner}">
</StackPanel>
use DataContext for Binding to Value1 in your ViewModel. Set the DataContext of both Windows to be the instance of your ViewModel:
public partial class MainWindow : Window
{
ViewModel viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = viewModel;
}
private void Properties1_Click(object sender, RoutedEventArgs e)
{
var newWindow = new PWMProperties();
newWindow.Owner = this;
newWindow.DataContext = viewModel;
newWindow.Show();
}
}

Data Binding in MVVM WPF

I have little knowledge in MVVM pattern. My problem is the data does not get binded to the xaml controls, no error is there. The progressbar is still at 0.
HomepageViewModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using CSMS_MVVM.Models;
namespace CSMS_MVVM.ViewModels
{
class HomepageViewModel : INotifyPropertyChanged
{
BackgroundWorker _worker;
public int _progress=20;
public int Progress
{
get { return _progress; }
set {
_progress = value;
OnPropertyChanged(new PropertyChangedEventArgs("Progress"));
}
}
public void startBackgroundProcess()
{
_worker = new BackgroundWorker();
_worker.DoWork += new DoWorkEventHandler(worker_DoWork);
_worker.ProgressChanged += worker_Progress_Changed;
_worker.RunWorkerAsync();
}
private void worker_Progress_Changed(object sender, ProgressChangedEventArgs e)
{
Progress = e.ProgressPercentage;
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
Progress = 20;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
#endregion
}
}
Homepage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CSMS_MVVM.ViewModels;
namespace CSMS_MVVM.Views
{
/// <summary>
/// Interaction logic for Homepage.xaml
/// </summary>
public partial class Homepage : Page
{
HomepageViewModel hvm;
public Homepage()
{
InitializeComponent();
}
private void Page_Loaded_1(object sender, RoutedEventArgs e)
{
hvm = new HomepageViewModel();
hvm.startBackgroundProcess();
}
}
}
Homepage.xaml
<Page x:Class="CSMS_MVVM.Views.Homepage"
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:CSMS_MVVM.ViewModels"
mc:Ignorable="d"
d:DesignHeight="700" d:DesignWidth="1000"
Title="Homepage" Loaded="Page_Loaded_1" Name="main">
<ProgressBar Name="pbStatus" Value="{Binding Path=Progress}" HorizontalAlignment="Center" Height="20" Margin="0,582,0,0" VerticalAlignment="Top" Width="300">
-----
<ProgressBar.Effect>
<DropShadowEffect Color="#FFB6B6B6" ShadowDepth="3" BlurRadius="15" Direction="310"/>
</ProgressBar.Effect>
</ProgressBar>
<TextBlock Text="{Binding Progress}" Margin="0,582,0,0" HorizontalAlignment="Center" VerticalAlignment="Top" />
<Label Content="Loading ..." HorizontalAlignment="Center" Margin="0,607,0,0" VerticalAlignment="Top"/>
------
</Page>
Am i doing the correct coding? I searched the internet for an example but i did not understand them.
Thanks!
All bindings you set will bind to the DataContext if nothing else is specified.
private void Page_Loaded_1(object sender, RoutedEventArgs e)
{
hvm = new HomepageViewModel();
hvm.startBackgroundProcess();
this.DataContext = hvm;
}
Once you have your data context set to your viewmodel instance, it should work.
You can set the DataContext of the page in the code behind.
Another option is to create the ViewModel as a XAML resource, and set the data context of the child element via Data Binding:
<Page x:Class="CSMS_MVVM.Views.Homepage"
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:CSMS_MVVM.ViewModels"
mc:Ignorable="d"
d:DesignHeight="700" d:DesignWidth="1000"
Title="Homepage" Loaded="Page_Loaded_1" Name="main">
<Page.Resources>
<!-- This creates the instance of the HomepageViewModel -->
<local:HomepageViewModel x:Key="HomepageViewModel" />
</Page.Resources>
<ProgressBar DataContext="{StaticResource HomepageViewModel}"
Value="{Binding Path=Progress}">
public Homepage()
{
InitializeComponent();
hvm = new HomepageViewModel();
this.DataContext=hvm;
}
Create view model object inside constructor.

wpf using DataTemplate into HierachicalDataTemplate

in Wpf application i've to show the same collection of items into a ListBox and TreeView, The List show only the first level, the TreeView the whole Hierarchical. My Question is: why in the TreeView is not applied the DataTemplate i declared for Item object? how do i can share the same DataTemplate across the 2 controls (the color of text into TV must be red)?
<Window x:Class="TestWpf.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"
xmlns:viewmodel="clr-namespace:TestWpf"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.Resources>
<DataTemplate DataType="{x:Type viewmodel:Item}">
<TextBlock Foreground="Red" Text="{Binding Caption}"></TextBlock>
</DataTemplate>
</Grid.Resources>
<ListBox Grid.Row="0" Name="lb1" ></ListBox>
<TreeView Name="tv1" Grid.Row="1" >
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type viewmodel:Item}" ItemsSource="{Binding Items}" >
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
MainWindow.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TestWpf
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ObservableCollection<Item> Items = new ObservableCollection<Item>();
var item1 = new Item("1");
Items.Add(item1);
item1.Items.Add(new Item("1.1"));
item1.Items.Add(new Item("1.2"));
item1.Items.Add(new Item("1.3"));
var item2 = new Item("2");
Items.Add(item2);
item2.Items.Add(new Item("2.1"));
item2.Items.Add(new Item("2.2"));
item2.Items.Add(new Item("2.3"));
var item3 = new Item("3");
Items.Add(item3);
item3.Items.Add(new Item("3.1"));
item3.Items.Add(new Item("3.2"));
item3.Items.Add(new Item("3.3"));
this.lb1.ItemsSource = Items;
this.tv1.ItemsSource = Items;
}
}
}
Item.cs
namespace TestWpf
{
public class Item
{
public List<Item> Items { get; set; }
public string Caption { get; set; }
public Item(string caption)
{
this.Caption = caption;
this.Items = new List<Item>();
}
}
}
I just copy and pasted your code in VS, pressed F5 and it worked.
The only thing i had to change was the namespace since i created it with WPFApplication1 :)
Try taking your code out to a fresh project and try to build it and see if it works.

Restore previous session after automatic log off in WPF

I want to implement feature in my WPF application like if someone has log in and he is filling a registration form,but after sometime the account is automatically logout(already implemented this feature),then when the user sign in again, then how to display him the application in the same old state i.e the half filled form or anything he was doing previously with his account,i am looking on net but unable to find any help on this.
There is no quick easy way to do this... However, I would do it like this.
Use the MVVM pattern. As the user enters info into the View, your ViewModel will get the data. When the user logs out, your application should serialize your ViewModel to your favorite format. Mine is JSON. Using JSON.NET, you can serialize the viewmodel out to file.
On startup, you would deserialize the file and restore your viewmodel. Voila, your view should be right back to where it was when they closed the app.
I have made it-
MainWindow.xaml
<Window x:Class="SerializeDeSerialize.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Nikita="clr-namespace:SerializeDeSerialize"
Title="MainWindow" Height="350" Width="525" Closed="Window_Closed_1" Loaded="Window_Loaded_1">
<Window.DataContext>
<Nikita:Movie></Nikita:Movie>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Name="lblTitle" Content="Title:" Grid.Row="0" Grid.Column="0" Margin="10,25,63,10" HorizontalAlignment="Left" Width="164"></Label>
<TextBox Grid.Row="0" Name="txtTitle" Grid.Column="1" Margin="10,25,63,10" Text="{Binding Title}"></TextBox>
<Label Grid.Row="1" Name="lblRating" Content="Rating:" Grid.Column="0" Margin="10,25,63,10" HorizontalAlignment="Left" Width="164"></Label>
<TextBox Grid.Row="1" Name="txtRating" Grid.Column="1" Margin="10,25,63,10" Text="{Binding Rating}"></TextBox>
<Label Grid.Row="2" Name="lblReleaseDate" Content="Release Date:" Grid.Column="0" Margin="10,25,63,10" HorizontalAlignment="Left" Width="164"></Label>
<TextBox Grid.Row="2" Name="txtReleaseDate" Grid.Column="1" Margin="10,25,63,10" Text="{Binding ReleaseDate}"></TextBox>
<Button Grid.Row="3" Content="Window1" Margin="66,36,69,10" Click="Button_Click_1"></Button>
<Button Grid.Row="4" Content="Window2" Margin="66,36,69,10" Click="Button_Click_2"></Button>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Serialization;
namespace SerializeDeSerialize
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
SerializeDeSerialize.Movie mv = new Movie();
static Movie mm = new Movie();
public MainWindow()
{
InitializeComponent();
DataContext = mv;
}
private void Window_Closed_1(object sender, EventArgs e)
{
SerializeToXML(mv);
}
static public void SerializeToXML(Movie movie)
{
XmlSerializer serializer = new XmlSerializer(typeof(Movie));
TextWriter textWriter = new StreamWriter(#"C:\Users\398780\Desktop\Nikita\movie.xml");
serializer.Serialize(textWriter, movie);
textWriter.Close();
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
mm=DeserializeFromXML();
txtTitle.Text = mm.Title;
txtRating.Text =Convert.ToString(mm.Rating);
txtReleaseDate.Text = Convert.ToString(mm.ReleaseDate);
}
static Movie DeserializeFromXML()
{
XmlSerializer deserializer = new XmlSerializer(typeof(Movie));
TextReader textReader = new StreamReader(#"C:\Users\398780\Desktop\Nikita\movie.xml");
mm=(Movie)deserializer.Deserialize(textReader);
textReader.Close();
return mm;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Window1 win1 = new Window1();
win1.Show();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
Window2 win2 = new Window2();
win2.Show();
}
}
}
MVVM-movie.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SerializeDeSerialize
{
public class Movie
{
private string _title;
private int _rating;
private DateTime _releaseDate;
public Movie()
{
}
public string Title
{
get { return _title; }
set { _title = value; }
}
public int Rating
{
get { return _rating; }
set { _rating = value; }
}
public DateTime ReleaseDate
{
get { return _releaseDate; }
set { _releaseDate = value; }
}
}
}
Please check..it is same as you told or not?

Drag on Drop onto a composite User Control with multiple text boxes

I have a user control that contains two text boxes, as well as some other controls. I want to be able to drag/drop a complex type onto this control, and I want the entire control to be a drop target, including the textboxes and space around the composited controls. When the data is dropped, it is split apart into component fields, each represented by the controls in the user control.
The problem I am having is that the textboxes (if I set AllowDrop to true) are trying to do their own drag drop thing, and will individually accept only the text format of the drop data. If I set AllowDrop to false on the textboxes, the drop is disabled the for the textboxes altogether. I can drag my complex data to labels, checkboxes etc, and it behaves exactly like I expect it should.
In addition the space around the other controls does not seem to be considered a valid drop target.
Any ideas how to make the text boxes behave as the controls (such as the labels, checkbox or combobox), and why the grid is not being considered a valid drop target?
Source for the user control:
<UserControl x:Class="DragDropTester.CompositeControl"
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="226" d:DesignWidth="428" AllowDrop="True">
<Grid AllowDrop="True">
<TextBox Height="23" Margin="115,12,12,0" Name="textBox1" VerticalAlignment="Top" AllowDrop="False" />
<Label Content="TextBox 1:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" Width="97" />
<TextBox Height="23" Margin="115,41,12,0" Name="textBox2" VerticalAlignment="Top" AllowDrop="False" />
<Label Content="TextBox 2:" Height="28" HorizontalAlignment="Left" Margin="12,41,0,0" Name="label2" VerticalAlignment="Top" Width="97" />
<CheckBox Content="CheckBox" Height="16" Margin="115,70,150,0" Name="checkBox1" VerticalAlignment="Top" />
<ComboBox Height="23" Margin="115,92,12,0" Name="comboBox1" VerticalAlignment="Top" />
</Grid>
</UserControl>
and code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DragDropTester {
/// <summary>
/// Interaction logic for CompositeControl.xaml
/// </summary>
public partial class CompositeControl : UserControl {
public CompositeControl() {
InitializeComponent();
PreviewDragEnter += new DragEventHandler(CompositeControl_DragEnter);
this.PreviewDragOver += new DragEventHandler(CompositeControl_DragEnter);
Drop += new DragEventHandler(CompositeControl_Drop);
}
void CompositeControl_Drop(object sender, DragEventArgs e) {
var complex = e.Data.GetData("ComplexDragData") as ComplexDragData;
if (complex != null) {
this.textBox1.Text = complex.Text1;
this.textBox2.Text = complex.Text2;
this.checkBox1.IsChecked = complex.BoolValue;
}
}
void CompositeControl_DragEnter(object sender, DragEventArgs e) {
var complex = e.Data.GetData("ComplexDragData") as ComplexDragData;
if (complex != null) {
e.Effects = DragDropEffects.Link;
} else {
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
}
}
And for the main window that hosts the user control and a drag source...
XAML:
<Window x:Class="DragDropTester.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:DragDropTester"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<src:CompositeControl />
<Label Content="Drag Source" Grid.Row="1" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="5" Background="LightGray" Name="lblDragSource" />
</Grid>
</Window>
C# code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DragDropTester {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
private Point _startPoint;
private bool _IsDragging;
public MainWindow() {
InitializeComponent();
lblDragSource.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(lblDragSource_PreviewMouseLeftButtonDown);
lblDragSource.PreviewMouseMove += new MouseEventHandler(lblDragSource_PreviewMouseMove);
}
void lblDragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
_startPoint = e.GetPosition(sender as IInputElement);
}
void lblDragSource_PreviewMouseMove(object sender, MouseEventArgs e) {
if (_startPoint == null) {
return;
}
if (e.LeftButton == MouseButtonState.Pressed && !_IsDragging) {
Point position = e.GetPosition(sender as IInputElement);
if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance) {
StartDrag(sender as DependencyObject);
}
}
}
private void StartDrag(DependencyObject dragSource) {
var data = new DataObject();
var dragData = new ComplexDragData { Text1 = "This is text1", Text2 = "This is text2", BoolValue = true };
data.SetData("ComplexDragData", dragData);
data.SetData(DataFormats.Text, dragData.ToString());
try {
_IsDragging = true;
DragDrop.DoDragDrop(dragSource, data, DragDropEffects.Copy | DragDropEffects.Link);
} finally {
_IsDragging = false;
}
}
}
public class ComplexDragData {
public String Text1 { get; set; }
public String Text2 { get; set; }
public bool BoolValue { get; set; }
public override string ToString() {
return string.Format("text1: {0} text2: {1} Bool: {2}", Text1, Text2, BoolValue );
}
}
}
Its looks like I can get the behavior I want by hooking the drag/drop events of the text boxes individually:
public CompositeControl() {
InitializeComponent();
PreviewDragEnter += new DragEventHandler(CompositeControl_DragEnter);
PreviewDragOver += new DragEventHandler(CompositeControl_DragEnter);
textBox1.PreviewDragEnter += new DragEventHandler(textBox_PreviewDragEnter);
textBox1.PreviewDragOver += new DragEventHandler(textBox_PreviewDragEnter);
textBox1.PreviewDrop += new DragEventHandler(CompositeControl_Drop);
textBox2.PreviewDragEnter += new DragEventHandler(textBox_PreviewDragEnter);
textBox2.PreviewDragOver += new DragEventHandler(textBox_PreviewDragEnter);
textBox2.PreviewDrop += new DragEventHandler(CompositeControl_Drop);
Drop += new DragEventHandler(CompositeControl_Drop);
}
void textBox_PreviewDragEnter(object sender, DragEventArgs e) {
e.Handled = true;
}
I'm here 8 years later to say this helped me. The MVVM version of this:
XAML
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewDragEnter">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="TextBoxIgnore"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDragOver">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="TextBoxIgnore"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDrop">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="TextBoxDrop"/>
</i:EventTrigger>
</i:Interaction.Triggers>
ViewModel
public void TextBoxIgnore(object sender, DragEventArgs args)
{
args.Handled = true;
}
public void TextBoxDrop(object sender, DragEventArgs args)
{
// handle the drop here.
}
Note: Using the following...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

Categories

Resources