UnityContainer new instances - wpf

I have a sample application with the following views:
MainWindow
NewCustomer
CustomerStep1
CustomerStep2
Home
I use unity to register Types in the App.xaml.cs.
I have constructor parameters as follows:
MainWindow(NewCustomer, Home)
NewCustomer(CustomerStep1, CustomerStep2)
The MainWindow the following xaml
<DockPanel>
<ToolBar DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
<Button Content="Home" Height="50" VerticalContentAlignment="Bottom" Width="100" Click="Button_Click" />
<Button Content="New Customer" Height="50" VerticalContentAlignment="Bottom" Width="100" Click="Button1_Click" />
</ToolBar>
<ContentControl x:Name="mainRegion" />
</DockPanel>
I have the viewmodels for each of them and all are working fine.
The problem I have is when I click New Customer and enter information in step 1 and step 2 and then I click on Home and click again on New Customer the data is not cleared. How do I clear the data from these objects.
Code behind of MainWindow I use:
private void Button_Click(object sender, RoutedEventArgs e)
{
mainRegion.Content = null;
mainRegion.Content = _homeView;
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
mainRegion.Content = null;
mainRegion.Content = _newCustomerView;
}
If I move away from the New Customer View and click on New Customer again, I would expect the form to be new. But it is not happening.
Thanks for your help!

How are you types registered?, what lifetime manager did you use?
This might also help - http://msdn.microsoft.com/en-us/library/ff660872(v=pandp.20).aspx

Related

c# wpf Dialog will close the owner window

i have a window that is acting like a Dialog with two buttons and a textbox, so its an input dialog, the problem is when i press the buttons, or close the dialog window in any way the main window that i used to create this dialog will get closed too! (exit code = 0) and another thing is that it will work OK in vs debugging but when i run the app without vs debugging that owner window get closed and in my case that window is the Main app window so the whole application will shutdown! what am i doing wrong?
XAML:
<Window x:Class="Server.Forms.Dialogs.PokeDialog"
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:Server.Forms.Dialogs"
mc:Ignorable="d"
Title="Poke" MinHeight="120" MinWidth="225"
ResizeMode="CanResizeWithGrip"
SizeToContent="WidthAndHeight"
x:Name="windowPoke"
Loaded="windowPoke_Loaded">
<StackPanel VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Margin="25">
<Label Content="Poke Reason:"
Padding="0"/>
<TextBox x:Name="textboxPokeReason"
Margin="0 5"/>
<DockPanel>
<Button x:Name="btnOk"
Click="btnOk_Click"
IsDefault="True"
Content="OK"
MinWidth="100"
Margin="0 0 5 0"/>
<Button x:Name="btnCancel"
Click="btnCancel_Click"
IsCancel="True"
Content="Cancel"
MinWidth="100"/>
</DockPanel>
</StackPanel>
C#:
public partial class PokeDialog : Window
{
public string PokeReason
{
get { return textboxPokeReason.Text; }
}
public PokeDialog()
{
InitializeComponent();
}
private void windowPoke_Loaded(object sender, RoutedEventArgs e)
{
textboxPokeReason.Focus();
}
private void btnOk_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
}
}
the way i used dialog:
private void btnPokeClient_Click(object sender, RoutedEventArgs e)
{
var dialog = new PokeDialog();
if (dialog.ShowDialog() == true)
{
MessageBox.Show("TRUE - input text:" + dialog.PokeReason);
}
else MessageBox.Show("FALSE");
}
i can see the messageboxes too, but after closing this message boxes the whole app will get closed

How to change collection images in silverlight?

My Design Code like this:
<Grid HorizontalAlignment="Left" Height="42" VerticalAlignment="Top" Width="302" Margin="12,471,0,0" Background="{StaticResource AppBarItemForegroundThemeBrush}">
<TextBlock HorizontalAlignment="Left" Margin="6,6,0,0" TextWrapping="Wrap" Text="Change Color" VerticalAlignment="Top" Height="26" Width="137" FontSize="18" Foreground="Black" />
<Image HorizontalAlignment="Left" Height="33" Margin="163,3,0,0" VerticalAlignment="Top" Width="41" Source="Assets/c1-1.png" x:Name="c1" Tapped="c1_Tapped" />
<Image HorizontalAlignment="Left" Height="32" Margin="212,4,0,0" VerticalAlignment="Top" Width="45" Source="Assets/c3-1.png" x:Name="c2" Tapped="c2_Tapped" RenderTransformOrigin="0.825,0.5" />
<Image HorizontalAlignment="Left" Height="33" Margin="262,3,0,0" VerticalAlignment="Top" Width="40" Source="Assets/c2-1.png" x:Name="c3" Tapped="c3_Tapped" />
</Grid>
Code Behind code like this:
private void c1_Tapped(object sender, TappedRoutedEventArgs e)
{
Images = new ObservableCollection<string>();
Images.Add(#"Assets/02_perspective_img_1.png");
Images.Add(#"Assets/02_perspective_img_2.png");
Images.Add(#"Assets/02_perspective_img_3.png");
this.DataContext = this;
}
private void c2_Tapped(object sender, TappedRoutedEventArgs e)
{
Images = new ObservableCollection<string>();
Images.Add(#"Assets/03_perspective_img_1.png");
Images.Add(#"Assets/03_perspective_img_2.png");
Images.Add(#"Assets/03_perspective_img_3.png");
this.DataContext = this;
}
private void c3_Tapped(object sender, TappedRoutedEventArgs e)
{
Images = new ObservableCollection<string>();
Images.Add(#"Assets/01_perspective_img_1.png");
Images.Add(#"Assets/01_perspective_img_2.png");
Images.Add(#"Assets/01_perspective_img_3.png");
this.DataContext = this;
}
When tapped on particular image need to show that particular images.But not showing that .
only showing first clicked items images only.Please let me know how to change the collection.
i am binding that collection to flipview control in windows 8.
<FlipView.ItemTemplate>
<DataTemplate>
<Image HorizontalAlignment="Left" Source="{Binding}" Height="450" VerticalAlignment="Top" Width="792" x:Name="imagecontrol" Stretch="Fill"/>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
I'm going under a few assumptions. One is that the FlipView control has it's ItemsSource binding to your Images property. If you are going to set the DataContext to yourself (the page in question) you need to do one of a few options.
One: Do not set Images to a new collection. You are using an ObservableCollection so take advantage of it. Clear the collection and add items back to it.
private void c3_Tapped(object sender, TappedRoutedEventArgs e)
{
Images.Clear();
Images.Add(#"Assets/01_perspective_img_1.png");
Images.Add(#"Assets/01_perspective_img_2.png");
Images.Add(#"Assets/01_perspective_img_3.png");
}
Two: Implement INotifyPropertyChanged in the page and fire the PropertyChanged event when you reset the Images property
private ICollection<string> _images;
public ICollection<string> Images
{
get { return _images; }
set
{
_images = value;
OnPropertyChanged("Images");
}
}
You will probably find that you will need more and more bindings. Because of this it is usually best to have a separate ViewModel class that holds your data.
the way Shawn is suggested is i will recommend but when i tested it in case of Windows 8 app page which is inherited by LayoutAwarePage then in that case - Firstly you got error that Page Can not Implement InotifypropertyChanged secondly when i Tested it With ObsevableCollection that time also it is not working..so i have come with this workaround for solving your problem. in this case you just have to update the itemsSource Property of your FlipView Control each time when you are updating your Image collection..
private void c1_Tapped(object sender, TappedRoutedEventArgs e)
{
Images = new ObservableCollection<string>();
Images.Add(#"Assets/02_perspective_img_1.png");
Images.Add(#"Assets/02_perspective_img_2.png");
Images.Add(#"Assets/02_perspective_img_3.png");
FlipviewControlName.ItemsSource = Images;
}
I know this is not the proper solution but i think i will solve your problem...

TextBlock MouseDown URL - How get my url in my code behind?

I ve a list from sharepoint and i collect from this list an hyperlink.
As i want my textbox to be like an hyperlink I ve added an event on mousedown to open this hyperlink, My concern is how to collect this hyperlink in the codebehind with the sender.
For the moment I've just hide this hyperlink in the tooltip maybe i can manage this differently any suggestion will be grantly appreciated.
My point so far, i don't know how to get this tooltip in the code behind.
Thanks
My XAML Code :
<ListBox Name="ListboxTips" ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Picture}" Height="20"></Image>
<TextBlock MouseDown="TextBlock_MouseDown_URL" TextDecorations="Underline"
Margin="10,10,20,10" Width="160" TextWrapping="Wrap"
Text="{Binding Path=TitleTip}"
ToolTip="{Binding Path=URL}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My code behind :
foreach (SPSClient.ListItem item in TipsList)
{
var tips = new Tips();
tips.TitleTip = item.FieldValues.Values.ElementAt(1).ToString();
tips.App = item.FieldValues.Values.ElementAt(4).ToString();
// get the Hyperlink field URL value
tips.URL = ((FieldUrlValue)(item["LinkDoc"])).Url.ToString();
//should collect the description of the url
//tips.URLdesc = ((FieldUrlValue)(item["LinkDoc"])).Description.ToString();
tips.Picture = item.FieldValues.Values.ElementAt(4).ToString();
colTips.Add(tips);
}
ListboxTips.DataContext = colTips;
....
private void TextBlock_MouseDown_URL(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//string test = (ToolTip)(sender as Control).ToString();
System.Diagnostics.Process.Start("http://www.link.com");
//System.Diagnostics.Process.Start(test);
}
Thanks a lot,
You can just access the property directly. It is not elegant, but will work!
private void TextBlock_MouseDown_URL(object sender, MouseButtonEventArgs e)
{
TextBlock txtBlock = sender as TexBlock;
// just access the property
string url = txtBlock.ToolTip as string;
}
A more elegant approach might be to use a Button, Hyperlink or something that exposes a Command, so that you can bind the 'click' action to a command on your view model that performs the action you wish to execute.
usually you stick any data you want to trespass somewhere to Tag attribute.
<TextBlock .. Tag="{Binding Path=URL}" />
This is easily retrievable as a public property:
private void TextBlock_MouseDown_URL(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var tb = sender as TextBlock;
if(tb != null)
{
var neededUrl = tb.Tag;
}
}

Visibility of 2 user component in Silverlight

In my application got one sidebar, which is holding this two component :
<Grid x:Name="AF" Visibility="Visibility">
<betata:AForm Height="508" VerticalAlignment="Top"/>
</Grid>
<Grid x:Name="AR" Visibility="Collapsed">
<betata:AReg Height="508" VerticalAlignment="Top"/>
</Grid>
in the AForm got hyperlink button with this method :
private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
betata.Views.Sidebar.Sidebar sd = new Sidebar();
sd.showAR(this);
}
back to my sidebar code got another method called showAR with these function :
public void showAR(AForm aForm)
{
this.AR.Visibility = Visibility.Visible;
aForm.Visibility = Visibility.Collapsed;
}
but i not sure why the aForm will collapsed but AR could not become visible.
I would refactor this a bit, to make it more simple (which might help to solve your problem).
<Grid>
<betat:AForm x:Name="aForm" Height="508" VerticalAlignment="Top" Visibility="Visible" />
<betata:AReg x:Name="aReg" Height="508" VerticalAlignment="Top" Visibility="Collapsed" />
</Grid>
public void showAR() // this is in the code behind (xaml.cs) of the Sidebar UserControl
{
this.aReg.Visibility = Visibility.Visible;
this.aForm.Visibility = Visibility.Collapsed;
}
or you don't even need the ShowAR() and could just set the visibility in the button click, unless you're reusing the function in other places.Example:
private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
betata.Views.Sidebar.Sidebar sd = new Sidebar();
sd.aReg.Visibility = Visibility.Visible;
sd.aForm.Visibility = Visibility.Collapsed;
}
Question had been answer in this post. Visibility of User Control can be solve via tunnelling and bubbling. which are new routing events function of silverlight

How to update Source property of a frame by clicking only one button from user control?

I’d like to find out about how to update a source property by clicking only one "Next" button based on a click count and being able to load different pages into frame each time the button is clicked another time. Any advice is highly appreciated! Thank you in advance.
Main Window Code:
<Grid x:Name="LayoutRoot">
<Frame Content="Frame" Source="/WpfApplication1;component/Page1.xaml"/>
<local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>
User control that contains the button:
<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">
<Button Content="Back" HorizontalAlignment="Left" Width="75"/>
<Button Content="Next" HorizontalAlignment="Left" Width="75" />
</StackPanel>
Create a PageViewModel class that implements NextPageCommand and PreviousPageCommand commands, which raise (respectively) UserNavigatedToNextPage and UserNavigatedToPreviousPage events. To make it simple, also have them expose NextPage and PreviousPage properties of type PageViewModel. Create subclasses of PageViewModel for each page.
Create a view model class for the owning UserControl that exposes a CurrentPage property of type PageViewModel. Create all of the PageViewModel objects and set NextPage and PreviousPage on each. Add handlers for the navigation events on these object that look something like:
public void Page_UserNavigatedToNextPage(object sender, EventArgs e)
{
if (sender == CurrentPage && CurrentPage.NextPage != null)
{
CurrentPage = CurrentPage.NextPage;
}
}
Assuming that you've implemented property-change notification, now whenever the current page's NextPageCommand or PreviousPageCommand executes, the CurrentPage property will be updated and will be reflected in the UI. If you've created a data template for each page view model type, all you need is
<ContentPresenter Content="{Binding CurrentPage}"/>
in your user control and you're good to go.
If the Next/Previous buttons are in your control, and not in the page, then implement properties in the main view model that expose CurrentPage.NextPageCommand and CurrentPage.PreviousPageCommand, and bind the buttons to them.
In your NavUserControl, I would wire up either events or commands (or both, perhaps) for the next and back buttons. Then you can access those from within the MainWindow and set the appropriate value into the Source property.
If you go the event route, attach onto the events and set the Source directly.
If you go the command route, setup a command in your viewmodel, bind it to the usercontrol, and bind the Source property to another value in your viewmodel.
Edit: Adding some code per the OP's request. Keep in mind, this is not intended to be best practices. Just some examples.
To go the event route should be the simplest. You already know how to do this, I'd imagine. Just add:
public event EventHandler BackClicked;
public event EventHandler NextClicked;
private void Back_Click(object sender, RoutedEventArgs e)
{
BackClicked(sender, e);
}
private void Next_Click(object sender, RoutedEventArgs e)
{
NextClicked(sender, e);
}
events to your NavUserControl. Then change your XAML to:
<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">
<Button Content="Back" HorizontalAlignment="Left" Width="75" Click="Back_Click" />
<Button Content="Next" HorizontalAlignment="Left" Width="75" Click="Next_Click" />
</StackPanel>
And now in your MainWindow.xaml.cs file, add:
private void BackClicked(object sender, EventArgs e)
{
Uri source = // Whatever your business logic is to determine the previous page;
_Frame.Source = source;
}
private void NextClicked(object sender, EventArgs e)
{
Uri source = // Whatever your business logic is to determine the next page;
_Frame.Source = source;
}
and change the MainWindow XAML to be:
<Grid x:Name="LayoutRoot">
<Frame x:Name="_Frame" Content="Frame"
Source="/WpfApplication1;component/Page1.xaml"/>
<local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom"
BackClicked="BackClicked" NextClicked="NextClicked" />
</Grid>
Going the command route takes a little more architecting, but is a lot more clean. I'd recommend using your favorite MVVM toolkit. My favorite is MVVMLight, so that's what I'll use for this example.
Create a ViewModel class, something like this:
public class ViewModel : GalaSoft.MvvmLight.ViewModelBase
{
private Uri _Source;
public Uri Source
{
get { return _Source; }
set
{
if (_Source != value)
{
_Source = value;
RaisePropertyChanged("Source");
}
}
}
private GalaSoft.MvvmLight.Command.RelayCommand _BackCommand;
public ICommand BackCommand
{
get
{
if (_BackCommand == null)
{
_BackCommand = new GalaSoft.MvvmLight.Command.RelayCommand(() =>
{
Uri source = // Whatever your business logic is to determine the previous page
Source = source;
});
}
return _BackCommand;
}
}
private GalaSoft.MvvmLight.Command.RelayCommand _NextCommand;
public ICommand NextCommand
{
get
{
if (_NextCommand == null)
{
_NextCommand = new GalaSoft.MvvmLight.Command.RelayCommand(() =>
{
Uri source = // Whatever your business logic is to determine the next page
Source = source;
});
}
return _NextCommand;
}
}
}
In your MainWindow.xaml.cs, create an instance of this class and set your DataContext property to that instance. Then setup your bindings:
<Grid x:Name="LayoutRoot">
<Frame Content="Frame" Source="{Binding Source}"/>
<local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>
and
<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">
<Button Content="Back" HorizontalAlignment="Left" Width="75" Command="{Binding BackCommand}"/>
<Button Content="Next" HorizontalAlignment="Left" Width="75" Command="{Binding NextCommand}" />
</StackPanel>
The binding example is pretty straight-forward MVVM-style WPF. I'd suggest you go that route and if you need more help, go read up on MVVM in WPF. Lots of resources out there in the form of tutorials and books. Searching here on SO can help a lot as well.
Edit again:
Change your constructor to this:
public MainWindow()
{
this.InitializeComponent();
// Insert code required on object creation below this point.
DataContext = new ViewModel();
}

Resources