how to show Loader on the xaml using mvvm - c#

Hi I have integrated usercontrol(Loader) on my xaml page.
I want to show this loader on the fronpage.
if some another pages is loading.
<control:LoadingAnimation x:Name="ldrControl" Margin="100,100,100,150" Visibility="{Binding IsLoaderVisibile}" />
I am able to show this control but when another pages are loading then It's hided.
I have to show this control in front of the pages.

this will work ,
xmlns:local="clr-namespace:WpfApplication156"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Width="{Binding RelativeSource={RelativeSource Self},
Path=Height,
Mode=TwoWay}"
Height="120"
Background="Transparent"
IsVisibleChanged="HandleVisibleChanged"
Opacity="0"
Visibility="Hidden">
<Viewbox HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Canvas Width="120"
Height="120"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Loaded="HandleLoaded"
RenderTransformOrigin="0.5,0.5"
Unloaded="HandleUnloaded">
<Canvas.Resources>
<Style TargetType="Ellipse">
<Setter Property="Width" Value="20" />
<Setter Property="Height" Value="20" />
<Setter Property="Stretch" Value="Fill" />
<Setter Property="Fill">
<Setter.Value>
<Binding Path="Foreground">
<Binding.RelativeSource>
<RelativeSource AncestorType="{x:Type local:ProgressBar}" Mode="FindAncestor" />
</Binding.RelativeSource>
</Binding>
</Setter.Value>
</Setter>
</Style>
</Canvas.Resources>
<Ellipse x:Name="C0" Opacity="1.0" />
<Ellipse x:Name="C1" Opacity="0.9" />
<Ellipse x:Name="C2" Opacity="0.8" />
<Ellipse x:Name="C3" Opacity="0.7" />
<Ellipse x:Name="C4" Opacity="0.6" />
<Ellipse x:Name="C5" Opacity="0.5" />
<Ellipse x:Name="C6" Opacity="0.4" />
<Ellipse x:Name="C7" Opacity="0.3" />
<Ellipse x:Name="C8" Opacity="0.2" />
<Canvas.RenderTransform>
<RotateTransform x:Name="SpinnerRotate" Angle="0" />
</Canvas.RenderTransform>
</Canvas>
</Viewbox>
</UserControl>
public partial class ProgressBar
{
#region Public Fields
/// <summary>
/// Spinning Speed. Default is 60, that's one rotation per second.
/// </summary>
public static readonly DependencyProperty RotationsPerMinuteProperty =
DependencyProperty.Register(
"RotationsPerMinute",
typeof(double),
typeof(ProgressBar),
new PropertyMetadata(60.0));
/// <summary>
/// Startup time in milliseconds, default is a second.
/// </summary>
public static readonly DependencyProperty StartupDelayProperty =
DependencyProperty.Register(
"StartupDelay",
typeof(int),
typeof(ProgressBar),
new PropertyMetadata(1000));
#endregion Public Fields
#region Private Fields
/// <summary>
/// Timer for the Animation.
/// </summary>
private readonly DispatcherTimer animationTimer;
/// <summary>
/// Mouse Cursor.
/// </summary>
private Cursor originalCursor;
#endregion Private Fields
#region Public Constructors
/// <summary>
/// Initializes a new instance of the ProgressBar class.
/// </summary>
public ProgressBar()
{
InitializeComponent();
this.animationTimer = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher);
}
#endregion Public Constructors
#region Public Properties
/// <summary>
/// Gets or sets the spinning speed. Default is 60, that's one rotation per second.
/// </summary>
public double RotationsPerMinute
{
get
{
return (double)this.GetValue(RotationsPerMinuteProperty);
}
set
{
this.SetValue(RotationsPerMinuteProperty, value);
}
}
/// <summary>
/// Gets or sets the startup time in milliseconds, default is a second.
/// </summary>
public int StartupDelay
{
get
{
return (int)this.GetValue(StartupDelayProperty);
}
set
{
this.SetValue(StartupDelayProperty, value);
}
}
#endregion Public Properties
#region Private Methods
/// <summary>
/// Apply a single rotation transformation.
/// </summary>
/// <param name="sender">Sender of the Event: the Animation Timer.</param>
/// <param name="e">Event arguments.</param>
private void HandleAnimationTick(object sender, EventArgs e)
{
this.SpinnerRotate.Angle = (this.SpinnerRotate.Angle + 36) % 360;
}
/// <summary>
/// Control was loaded: distribute circles.
/// </summary>
/// <param name="sender">Sender of the Event: I wish I knew.</param>
/// <param name="e">Event arguments.</param>
private void HandleLoaded(object sender, RoutedEventArgs e)
{
this.SetPosition(C0, 0.0);
this.SetPosition(C1, 1.0);
this.SetPosition(C2, 2.0);
this.SetPosition(C3, 3.0);
this.SetPosition(C4, 4.0);
this.SetPosition(C5, 5.0);
this.SetPosition(C6, 6.0);
this.SetPosition(C7, 7.0);
this.SetPosition(C8, 8.0);
}
/// <summary>
/// Control was unloaded: stop spinning.
/// </summary>
/// <param name="sender">Sender of the event.</param>
/// <param name="e">Event arguments.</param>
private void HandleUnloaded(object sender, RoutedEventArgs e)
{
this.StopSpinning();
}
/// <summary>
/// Visibility property was changed: start or stop spinning.
/// </summary>
/// <param name="sender">Sender of the event.</param>
/// <param name="e">Event arguments.</param>
private void HandleVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
// Don't give the developer a headache.
////if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
////{
//// return;
////}
bool isVisible = (bool)e.NewValue;
if (isVisible)
{
this.StartDelay();
}
else
{
this.StopSpinning();
}
}
/// <summary>
/// Calculate position of a circle.
/// </summary>
/// <param name="ellipse">The circle.</param>
/// <param name="sequence">Sequence number of the circle.</param>
private void SetPosition(Ellipse ellipse, double sequence)
{
ellipse.SetValue(
Canvas.LeftProperty,
50.0 + (Math.Sin(Math.PI * ((0.2 * sequence) + 1)) * 50.0));
ellipse.SetValue(
Canvas.TopProperty,
50 + (Math.Cos(Math.PI * ((0.2 * sequence) + 1)) * 50.0));
}
/// <summary>
/// Startup Delay.
/// </summary>
private void StartDelay()
{
this.originalCursor = Mouse.OverrideCursor;
Mouse.OverrideCursor = Cursors.Wait;
// Startup
this.animationTimer.Interval = new TimeSpan(0, 0, 0, 0, this.StartupDelay);
this.animationTimer.Tick += this.StartSpinning;
this.animationTimer.Start();
}
/// <summary>
/// Start Spinning.
/// </summary>
/// <param name="sender">Sender of the event.</param>
/// <param name="e">Event Arguments.</param>
private void StartSpinning(object sender, EventArgs e)
{
this.animationTimer.Stop();
this.animationTimer.Tick -= this.StartSpinning;
// 60 secs per minute, 1000 millisecs per sec, 10 rotations per full circle:
this.animationTimer.Interval = new TimeSpan(0, 0, 0, 0, (int)(6000 / this.RotationsPerMinute));
this.animationTimer.Tick += this.HandleAnimationTick;
this.animationTimer.Start();
this.Opacity = 1;
Mouse.OverrideCursor = this.originalCursor;
}
/// <summary>
/// The control became invisible: stop spinning (animation consumes CPU).
/// </summary>
private void StopSpinning()
{
this.animationTimer.Stop();
this.animationTimer.Tick -= this.HandleAnimationTick;
this.Opacity = 0;
}
#endregion Private Methods
}
//********************************************
IsLoaded=true; set in Relay Command
IsLoaded =false;
private Visibility isLoaded;
public Visibility IsLoaded
{
get
{
return this.isLoaded;
}
set
{
this.isLoaded = value;
RasisePropertyChange("IsLoaded");
}
}
<vm:ProgressBar x:Name="ProgressBar"
Grid.Row="2"
Grid.Column="1"
Width="140"
Margin="12"
Padding="10"
Visibility="{Binding IsLoaded}">
<vm:ProgressBar.Foreground>
<RadialGradientBrush Center="0.5,0.5" GradientOrigin="0.4,0.4" RadiusX="0.5" RadiusY="0.5">
<RadialGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Transparent" />
<GradientStop Offset="1" Color="DimGray" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</vm:ProgressBar.Foreground>
</vm:ProgressBar>

Related

How to get Buttons content as property in a called flyout in an UWP app?

Usecase
I've a bunch (8) of buttons which opens an Flyover via the set style property.
The flyover contains an "Apply" button. The button will trigger an Command which does something in the view model related to the source's buttons content (which is 1 to 8).
Problem
How get I the content value of my button that triggers the Flyover to my command?
I thought that CommandParameter={Text ElementName=Source} should do what I want, but no it did not.
Resources
<Style x:Key="PixelButtonStyle" TargetType="Button">
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="50" />
<Setter Property="Margin" Value="5" />
<Setter Property="Flyout" Value="{StaticResource PixelColorPickerFlyOut}" />
</Style>
<Flyout x:Key="PixelColorPickerFlyOut">
<StackPanel>
<!-- Picker -->
<ColorPicker x:Name="PixelColorPicker"
IsAlphaEnabled="False"
IsColorChannelTextInputVisible="False"
IsAlphaSliderVisible="False"
IsAlphaTextInputVisible="False"
IsHexInputVisible="False"
IsColorSliderVisible="False"
Width="300"/>
<!-- Button row -->
<StackPanel Orientation="Horizontal"
Margin="0 20 0 0">
<Button Content="Apply"
Width="100"
Margin="0 0 10 0"
Command="{Binding ApplyColorCommand}"/>
<Button Content="Cancel"
Width="100"/>
<TextBlock Text="{Binding Path=Source}" />
</StackPanel>
</StackPanel>
</Flyout>
Usage
<Button Style="{StaticResource PixelButtonStyle}" Content="" />
Update 1
I also tried to use as flyout button:
<Button Command="{Binding ElementName=Grid, Path=DataContext.ApplyColorPickerCommand}"
Content="Apply" />
and as button that triggeres the flyout:
<Button Style="{StaticResource PixelButtonStyle}"
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"
Content="1"
Background="Green"/>
but it had no positive effect.
I'm not so sure if I understand your request properly. Do you actually mean this, you have 8 buttons and each of them can raise the flyout. So you want to know which button actually raised the flyout? If this is what you want, maybe you can give the following code a try:
First, each FramewrokElement has a property called tag. So here is a demo XAML:
<Grid>
<Button Tag="button no.1" Command="{Binding MyBtnClickCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self},Path=Tag}" Content="set empty content"/>
</Grid>
Then if you are using RelayCommand, we can get the tag value from this class:
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
/// <summary>
/// Raised when RaiseCanExecuteChanged is called.
/// </summary>
public event EventHandler CanExecuteChanged;
/// <summary>
/// Creates a new command that can always execute.
/// </summary>
/// <param name="execute">The execution logic.</param>
public RelayCommand(Action execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action execute, Func<bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
/// <summary>
/// Determines whether this RelayCommand can execute in its current state.
/// </summary>
/// <param name="parameter">
/// Data used by the command. If the command does not require data to be passed,
/// this object can be set to null.
/// </param>
/// <returns>true if this command can be executed; otherwise, false.</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute();
}
/// <summary>
/// Executes the RelayCommand on the current command target.
/// </summary>
/// <param name="parameter">
/// Data used by the command. If the command does not require data to be passed,
/// this object can be set to null.
/// </param>
///
**private string btntag;
public string BtnTag
{
get { return btntag; }
set { btntag= value; }
}**
public void Execute(object parameter)
{
**btntag= parameter as string;**
_execute();
}
/// <summary>
/// Method used to raise the CanExecuteChanged event
/// to indicate that the return value of the CanExecute
/// method has changed.
/// </summary>
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
And finally, you can get it in your command:
private RelayCommand btnclickcommmand;
public RelayCommand MyBtnClickCommand
{
get { return btnclickcommmand; }
set { btnclickcommmand = value; }
}
btnclickcommmand = new RelayCommand(() =>
{
//TODO
mytag = btnclickcommmand.BtnTag;
System.Diagnostics.Debug.WriteLine(mytag+"Button create the flyout");
});

Update TextBlock with binding not working

I have a question about databinding!
I am writing code for a 'node editor' that has some (different) nodes in it.
I use a BaseViewModel class that derives from INotifyPropertyChanged.
There is a 'base' NodeViewModel (that derives from it) with an ObservableCollection and other Properties, like the Node's Name property. It's implementation looks like this:
(in public class NodeViewModel : BaseViewModel):
protected String mName = String.Empty;
public String Name {
get { return mName; }
set {
if (mName == value) {
return;
}
mName = value;
OnPropertyChanged("Name");
}
}
With an OnPropertyChanged handler that looks like this:
(in BaseViewModel)
protected virtual void OnPropertyChanged(string propertyName) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Now I have one additional RoomViewModel that derives from NodeViewModel.
I use another different ViewModel that I call RoomCollectionViewModel to group some rooms.
Now when I add a room to my roomcollection (by drawing a connection between them) I test all connected rooms for the same name.
If an already connected room exists in the collection with the same room name (e.g. "new room") I want to change those two room's names to e.g. "new room #1" and "new room #2". No problem so far.
Every node control (created using DataTemplates with set DataContext set to the ViewModel) contains a TextBlock (a modified one) that displays the node's name.
This is where it gets problematic:
I use a modified Textblock because I want to be able to modify the node's name by double-clicking on it. And that works perfectly, only if I modify the RoomViewModel's name in Code, this (modified) TextBlock won't update.
The strange thing is this:
When two equally named rooms in a collection get renamed by my code and I then double-click on the editable TextBlock (which converts to a TextBox in that process), I already see the modified Text. So I assume my DataBinding and my code is correct, just not complete :)
So how is it possible to force an update of my EditableTextBlock, the Text (DependencyProperty) seems to be updated correctly...
I hope you understand what my problem is! Thank you for any help.
Update 1
This is the XAML code for my EditableTextBlock (it comes from here: http://www.codeproject.com/Articles/31592/Editable-TextBlock-in-WPF-for-In-place-Editing)
<UserControl x:Class="NetworkUI.EditableTextBlock"
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:NetworkUI"
mc:Ignorable="d"
d:DesignHeight="60" d:DesignWidth="240" x:Name="mainControl">
<UserControl.Resources>
<DataTemplate x:Key="EditModeTemplate">
<TextBox KeyDown="TextBox_KeyDown" Loaded="TextBox_Loaded" LostFocus="TextBox_LostFocus"
Text="{Binding ElementName=mainControl, Path=Text, UpdateSourceTrigger=PropertyChanged}"
Margin="0" BorderThickness="1" />
</DataTemplate>
<DataTemplate x:Key="DisplayModeTemplate">
<TextBlock Text="{Binding ElementName=mainControl, Path=FormattedText}" Margin="5,3,5,3" MouseDown="TextBlock_MouseDown" />
</DataTemplate>
<Style TargetType="{x:Type local:EditableTextBlock}">
<Style.Triggers>
<Trigger Property="IsInEditMode" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource EditModeTemplate}" />
</Trigger>
<Trigger Property="IsInEditMode" Value="False">
<Setter Property="ContentTemplate" Value="{StaticResource DisplayModeTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
And here is the code-behind file:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace NetworkUI {
/// <summary>
/// Interaction logic for EditableTextBlock.xaml
/// </summary>
public partial class EditableTextBlock : UserControl {
#region Dependency Properties, Events
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(String), typeof(EditableTextBlock),
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static readonly DependencyProperty IsEditableProperty =
DependencyProperty.Register("IsEditable", typeof(Boolean), typeof(EditableTextBlock), new PropertyMetadata(true));
public static readonly DependencyProperty IsInEditModeProperty =
DependencyProperty.Register("IsInEditMode", typeof(Boolean), typeof(EditableTextBlock), new PropertyMetadata(false));
public static readonly DependencyProperty TextFormatProperty =
DependencyProperty.Register("TextFormat", typeof(String), typeof(EditableTextBlock), new PropertyMetadata("{0}"));
#endregion ///Dependency Properties, Events
#region Variables and Properties
/// <summary>
/// We keep the old text when we go into editmode
/// in case the user aborts with the escape key
/// </summary>
private String oldText;
/// <summary>
/// Text content of this EditableTextBlock
/// </summary>
public String Text {
get { return (String)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
/// <summary>
/// Is this EditableTextBlock editable or not
/// </summary>
public Boolean IsEditable {
get { return (Boolean)GetValue(IsEditableProperty); }
set { SetValue(IsEditableProperty, value); }
}
/// <summary>
/// Is this EditableTextBlock currently in edit mode
/// </summary>
public Boolean IsInEditMode {
get {
if (IsEditable)
return (Boolean)GetValue(IsInEditModeProperty);
else
return false;
}
set {
if (IsEditable) {
if (value)
oldText = Text;
SetValue(IsInEditModeProperty, value);
}
}
}
/// <summary>
/// The text format for the TextBlock
/// </summary>
public String TextFormat {
get { return (String)GetValue(TextFormatProperty); }
set {
if (value == "")
value = "{0}";
SetValue(TextFormatProperty, value);
}
}
/// <summary>
/// The formatted text of this EditablTextBlock
/// </summary>
public String FormattedText {
get { return String.Format(TextFormat, Text); }
}
#endregion ///Variables and Properties
#region Constructor
/// <summary>
/// Default constructor for the editable text block
/// </summary>
public EditableTextBlock() {
InitializeComponent();
Focusable = true;
FocusVisualStyle = null;
}
#endregion ///Constructor
#region Methods, Functions and Eventhandler
/// <summary>
/// Invoked when we enter edit mode
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
void TextBox_Loaded(object sender, RoutedEventArgs e) {
TextBox txt = sender as TextBox;
/// Give the TextBox input focus
txt.Focus();
txt.SelectAll();
}
/// <summary>
/// Invoked when we exit edit mode
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
void TextBox_LostFocus(object sender, RoutedEventArgs e) {
IsInEditMode = false;
}
/// <summary>
/// Invoked when the user edits the annotation.
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
void TextBox_KeyDown(object sender, KeyEventArgs e) {
if (e.Key == Key.Enter) {
IsInEditMode = false;
e.Handled = true;
}
else if (e.Key == Key.Escape) {
IsInEditMode = false;
Text = oldText;
e.Handled = true;
}
}
/// <summary>
/// Invoked when the user double-clicks on the textblock
/// to edit the text
/// </summary>
/// <param name="sender">Sender (the Textblock)</param>
/// <param name="e">Event arguments</param>
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e) {
if (e.ClickCount == 2)
IsInEditMode = true;
}
#endregion ///Methods, Functions and Eventhandler
}
Thank you for any help!
Update 2
I changed the following line of code:
<TextBlock Text="{Binding ElementName=mainControl, Path=FormattedText}" Margin="5,3,5,3" MouseDown="TextBlock_MouseDown" />
to:
<TextBlock Text="{Binding ElementName=mainControl, Path=Text}" Margin="5,3,5,3" MouseDown="TextBlock_MouseDown" />
and now it is working!
I didn't see the TextBlock using the FormattedText in the first place! Ugh, thank you very much, now everything updates perfectly!
As postes by Lee O. the problem was indeed the bound property from my EditableTextBlock control.
The TextBlock used the FormattedText property that was updated by my Binding. Now I use the Text property for both, the TextBlock and the TextBox controls.
I simply removed the FormattedText property as well as the TextFormatProperty (DependencyProperty) and TextFormat property from my EditableTextBlock because I didn't plan to use those.
Thank you again!

Outofmemoryexception in binding datagrid

I have a outofmemoryexception . I am trying to retrieve from CRM over 7000 accounts and stock into the list of contratvuemodele. This list will be add to the observablecollection of contratvuemodele and bind to datagrid.
But my application do not work.
here is my codes:
code xaml:
<UserControl x:Class="GestionDeContrats_Offres_ClientsGUI.VueModele.UserControlGestionContrat"
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"
x:Name="GestionContrat"
xmlns:local="clr-namespace:GestionDeContrats_Offres_ClientsGUI.VueModele"
d:DesignHeight="300" >
<!-- <UserControl.DataContext>
<local:GestionDeContratVueModele />
</UserControl.DataContext>
-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="40"/>
<RowDefinition />
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="320"/>
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<TextBox Name="searchtexbox" Grid.Column="0"/>
<Image Grid.Column="1" Source="/GestionDeContrats_Offres_ClientsGUI;component/Images/16_find.gif" />
</Grid>
<ToolBar Grid.Row="1" Name="toolbarcontrat">
<Button Name="btNewContrat" Click="btNewContrat_Click">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="/GestionDeContrats_Offres_ClientsGUI;component/Images/plusvert.jpg" />
<Label Content="Nouveau" Grid.Column="1"/>
</Grid>
</Button>
<Button Name="btCopierContrat" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="/GestionDeContrats_Offres_ClientsGUI;component/Images/editcopy.png" />
<Label Content="Copier" Grid.Column="1"/>
</Grid>
</Button>
<Button Name="btSupprimerContrat" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="/GestionDeContrats_Offres_ClientsGUI;component/Images/delgreen16.jpg" />
<Label Content="Supprimer" Grid.Column="1"/>
</Grid>
</Button>
<Button Name="btModifierContrat" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="/GestionDeContrats_Offres_ClientsGUI;component/Images/ico_18_4207.gif" />
<Label Content="Modifier" Grid.Column="1"/>
</Grid>
</Button>
</ToolBar>
<DataGrid Name="listViewContrat" Grid.Row="2" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding Path=Lescontrats, Mode=OneWay}" IsSynchronizedWithCurrentItem="True" AutoGenerateColumns="False" CanUserReorderColumns="True" CanUserResizeColumns="True" CanUserSortColumns="True" CanUserAddRows="True" CanUserDeleteRows="True">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Nom du contrat" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=NOMDUCONTRAT, Mode=OneWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Date de début" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=DATEDEDEBUT, Mode=OneWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Date de fin" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=DATEDEFIN, Mode=OneWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Statut" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=LESTATUT,Mode=OneWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Statut avant" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text=""/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="3" Orientation="Horizontal">
<Label Margin="2" Content=""/>
<Button Content="Suivant" Name="btNext" Margin="2" />
<Button Content="Précédent" Name="btPrevious" Margin="2" />
</StackPanel>
</Grid>
</UserControl>
code cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GestionDeContrats_Offres_ClientsGUI.VueModele;
using System.Collections.ObjectModel;
using System.Windows.Data;
using System.ComponentModel;
using GestionDeContrats_Offres_Clients.GestionOffres;
using GestionDeContrats_Offres_Clients.GestionContrats;
using System.Windows.Input;
using GestionDeContrats_Offres_Clients.GestionModele;
using GestionDeContrats_Offres_ClientsGUI.crm;
using System.Data;
namespace GestionDeContrats_Offres_ClientsGUI.VueModele
{
/// <summary>
///
/// </summary>
public class GestionDeContratVueModele : VueModeleBase
{
private readonly ObservableCollection<ContratVueModele> contrats;
private readonly ICollectionView collectionView;
//private readonly PagingCollectionView pagingView;
private GestionDeContrat gestiondecontrat;
private ICommand activerContratCommand;
private ICommand supprimerContratCommand;
private ICommand modifierContratCommand;
private ICommand copierContratCommand;
private ICommand creerContratCommand;
private ICommand nextPageCommand;
private ICommand previousPageCommand;
private int currentpage;
/// <summary>
/// Constructeur de la classe
/// GestionDeContratVueModele
/// </summary>
public GestionDeContratVueModele() {
try
{
this.gestiondecontrat = new GestionDeContrat();
List<ContratVueModele> maliste = new List<ContratVueModele>(10000);
//maliste.Clear();
// this.contrats.Clear();
foreach (contract contrat in this.gestiondecontrat.ListeDeContrat())
{
// this.contrats.Add(new ContratVueModele());
maliste.Add(new ContratVueModele() { NOMDUCONTRAT = contrat.title, DATEDEDEBUT = contrat.activeon.Value, DATEDEFIN = contrat.expireson.Value, LESTATUT = contrat.statecode.formattedvalue, LESTATUTAVANT = contrat.access_etatavant.name });
// this.contrats.Add(new ContratVueModele() { NOMDUCONTRAT = contrat.title, DATEDEDEBUT = contrat.activeon.Value, DATEDEFIN = contrat.expireson.Value, LESTATUT = contrat.statecode.formattedvalue,LESTATUTAVANT=contrat.access_etatavant.name });
}
this.contrats = new ObservableCollection<ContratVueModele>(maliste);
this.collectionView = CollectionViewSource.GetDefaultView(this.contrats);
if (this.collectionView == null)
throw new NullReferenceException("collectionView");
// this.collectionView.CurrentChanged += new EventHandler(collectionView_CurrentChanged);
// this.pagingView = new PagingCollectionView(this.contrats, 15);
//if (this.pagingView == null)
//throw new NullReferenceException("pagingView");
//this.currentpage = this.pagingView.CurrentPage;
//this.pagingView.CurrentChanged += new EventHandler(pagingView_CurrentChanged);
}
catch (System.Web.Services.Protocols.SoapException soapEx)
{
soapEx.Detail.OuterXml.ToString();
}
catch (System.OutOfMemoryException memoryException)
{
memoryException.InnerException.ToString();
}
catch (System.Reflection.TargetInvocationException targetex) {
targetex.InnerException.ToString();
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
//void pagingView_CurrentChanged(object sender, EventArgs e)
//{
// OnPropertyChanged("SelectedContrat");
// Dispose();
// //throw new NotImplementedException();
//}
/// <summary>
///
/// </summary>
/// <param name="gestiondecontrat"></param>
public GestionDeContratVueModele(GestionDeContrat gestiondecontrat)
{
this.gestiondecontrat = gestiondecontrat;
this.contrats = new ObservableCollection<ContratVueModele>();
foreach (contract contrat in this.gestiondecontrat.ListeDeContrat())
{
this.contrats.Add(new ContratVueModele() { NOMDUCONTRAT=contrat.title,DATEDEDEBUT=contrat.activeon.Value, DATEDEFIN=contrat.expireson.Value,LESTATUT=contrat.statecode.formattedvalue});
}
this.collectionView = CollectionViewSource.GetDefaultView(this.contrats);
if (this.collectionView == null)
throw new NullReferenceException("collectionView");
this.collectionView.CurrentChanged += new EventHandler(collectionView_CurrentChanged);
}
/// <summary>
///
/// </summary>
public ICommand ActiverContratCommand {
get
{
if (this.activerContratCommand == null)
this.activerContratCommand = new CommandeDeRelais(() => this.ActiverContrat(), () => this.CanActiverContrat());
return this.activerContratCommand;
}
}
/// <summary>
///
/// </summary>
public ICommand CopierContratCommand
{
get
{
if (this.copierContratCommand == null)
this.copierContratCommand = new CommandeDeRelais(() => this.CopierContrat(), () => this.CanCopierContrat());
return this.copierContratCommand;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private bool CanCopierContrat()
{
return true;
//throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
private void CopierContrat()
{
this.gestiondecontrat.copier();
//throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
//public ICommand NextPageCommand {
// get {
// if(this.nextPageCommand==null)
// this.nextPageCommand = new CommandeDeRelais(() => this.NextPage(), () => this.CanNextPage());
// return nextPageCommand;
// }
//}
/// <summary>
///
/// </summary>
//private void NextPage() {
// this.pagingView.MoveToNextPage();
//}
/// <summary>
///
/// </summary>
/// <returns></returns>
//private bool CanNextPage() {
// return this.pagingView.PageCount > 1;//true; //Todo à reimplementer correctement
//}
/// <summary>
/// Permet de gérer le passage à la page précedente
/// </summary>
//private void PreviousPage()
//{
// this.pagingView.MoveToPreviousPage();
//}
/// <summary>
/// Vérifie si on peut passer à la page précédente
/// </summary>
/// <returns>un booléen qui nous dit si on peut passer à la commande précédente</returns>
//private bool CanPreviousPage()
//{
// return this.pagingView.MoveCurrentToPrevious();//true; //Todo à reimplementer correctement
//}
/// <summary>
/// Lecteur qui prend en charge la commande associée au bouton
/// </summary>
//public ICommand PreviousPageCommand
//{
// get
// {
// if (this.previousPageCommand==null)
// this.previousPageCommand = new CommandeDeRelais(() => this.PreviousPage(), () => this.CanPreviousPage());
// return previousPageCommand;
// }
//}
/// <summary>
/// Lecteur de la page courante
/// </summary>
public int CURRENTPAGE {
get {
return this.currentpage;
}
}
/// <summary>
/// Lecteur qui prend en charge la Commande qui s'exécute quand on appuie sur le bouton créer
/// ce bouton sera lié à cette propriété
/// </summary>
public ICommand CreerContratCommand {
get
{
if (this.creerContratCommand == null)
this.creerContratCommand = new CommandeDeRelais(() => this.CreerContrat(), () => this.CanCreerContrat());
return this.creerContratCommand;
}
}
/// <summary>
/// Lecteur sur la commande supprimer le contrat
/// </summary>
public ICommand SupprimerContratCommand {
get {
if (this.supprimerContratCommand == null)
this.supprimerContratCommand = new CommandeDeRelais(() => this.SupprimerContrat(), () => this.CanSupprimerContrat());
return this.supprimerContratCommand;
}
}
/// <summary>
///
/// </summary>
public ICommand ModifierContratCommand {
get {
if (this.modifierContratCommand == null)
this.modifierContratCommand = new CommandeDeRelais(() => this.ModifierContrat(), () => this.CanModifierContrat());
return this.modifierContratCommand;
}
}
/// <summary>
/// Propriété permettant de manipuler la
///Vue Modèle de la liste des contrats
/// </summary>
public ObservableCollection<ContratVueModele> Lescontrats
{
get
{
return this.contrats;
}
}
/// <summary>
/// Propriété permettant de manipuler la vue modèle
/// de selection du contrat
/// </summary>
public ContratVueModele SelectedContrat
{
get
{
return this.collectionView.CurrentItem as ContratVueModele;
}
}
/// <summary>
/// Propriété permettant manipuler la vue modèle qui vérifie si
/// que la vue est vide
/// </summary>
public bool SearchContainsNoMatch
{
get
{
return this.collectionView.IsEmpty;
}
}
/// <summary>
/// Propriété permettant manipuler la vue modèle
/// de recherche du contrat en fonction du nom ou du statut
/// </summary>
public string RechercheText
{
set
{
this.collectionView.Filter = (item) =>
{
if (item as ContratVueModele == null)
return false;
ContratVueModele contratvueModele = (ContratVueModele)item;
if (contratvueModele.NOMDUCONTRAT.Contains(value) || contratvueModele.LESTATUT.Contains(value))
return true;
return false;
};
this.OnPropertyChanged("SearchContainsNoMatch");
}
}
/// <summary>
/// Handler pour la sélection du contrat
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void collectionView_CurrentChanged(object sender, EventArgs e)
{
OnPropertyChanged("SelectedContrat");
//Dispose();
//throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
private void CreerContrat() {
try
{
this.gestiondecontrat.creer();
foreach (contract contrat in this.gestiondecontrat.ListeDeContrat())
{
this.contrats.Add(new ContratVueModele() { NOMDUCONTRAT=contrat.title, DATEDEDEBUT=contrat.activeon.Value, DATEDEFIN=contrat.expireson.Value, ADRESSE=contrat.serviceaddress.name, NET=contrat.netprice.Value});
}
}
catch(Exception creerEx){
creerEx.Message.ToString();
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private bool CanCreerContrat() {
return true;
}
/// <summary>
///
/// </summary>
private void ActiverContrat()
{
try
{
this.gestiondecontrat.ActiverContrat(this.SelectedContrat.CONTRAT);
}
catch (Exception activerEx)
{
activerEx.Message.ToString();
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private bool CanActiverContrat()
{
return this.SelectedContrat.LESTATUT != "Annulé";
}
/// <summary>
///
/// </summary>
private void SupprimerContrat()
{
try
{
this.gestiondecontrat.supprimer();
this.contrats.Remove(new ContratVueModele(this.SelectedContrat.CONTRAT));
}
catch (Exception supprimerEx)
{
supprimerEx.Message.ToString();
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private bool CanSupprimerContrat()
{
return this.contrats.Count>0;//true;
}
/// <summary>
///
/// </summary>
private void ModifierContrat() {
this.gestiondecontrat.modifier();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private bool CanModifierContrat() {
return this.SelectedContrat != null;
}
/// <summary>
///
/// </summary>
private void OuvrirDocumentContrat()
{
try
{
// Contrat newContrat = this.gestiondecontrat.CreerContrat(new Contrat(new ModeleDeContrat()));
//this.contrats.Add(new ContratVueModele(newContrat));
}
catch (Exception OuvrirDocumentContratEx)
{
OuvrirDocumentContratEx.Message.ToString();
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private bool CanOuvrirDocumentContrat()
{
return true;
}
}
}
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 GestionDeContrats_Offres_ClientsGUI.VueModele
{
/// <summary>
/// Logique d'interaction pour UserControlGestionContrat.xaml
/// </summary>
public partial class UserControlGestionContrat : UserControl
{
private readonly GestionDeContratVueModele vuemodelecontrat;
/// <summary>
///
/// </summary>
public UserControlGestionContrat()
{
InitializeComponent();
this.vuemodelecontrat = new GestionDeContratVueModele();
this.DataContext = this.vuemodelecontrat;
}
}
}
In my MainWindow.xaml i just integrate all usercontrol
Thanks
Best regards
i resolved a part of this problem by using listview, by making some changes on design. i made somes methods and called this in my constructor, now adding on list is making into these methods. I also change binding mode.
Now i have another problem.
When i run my solution on visual studio it takes a lot of time more then half an hour.it consumes many resources. and it is not finished correctly.

Tab Navigation on Virtualized Items Panel

How can you set the Tab Navigation on virtualized items? As example;
<ListBox x:Name="Items">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel VirtualizingStackPanel.VirtualizationMode="Recycling"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Button />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If I set TabNavigation=Once or Cycle on the Scrollviewer itself, or the Listbox parent etc, it only tabs through items available in the viewport since the others haven't been generated yet. Is there a trick someone might share for when tabbing through Item Objects it will allow Tab to proceed to the next not-yet-virtualized item while bringing it to view in the viewport and providing intuitive tabbing through the controls?
So basically what was came up (thanks to the extra eyes and help of another fine dev) with was to go ahead and render the other items but while remaining virtualized from onload with a custom behavior and at the same time exposing a dependency for continuous scrolling and bringing the current item into view in the viewport;
namespace The.Namespace
{
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
/// <summary>
/// Scroll selected item into view.
/// </summary>
public class ListBoxFocusBehavior : FocusBehavior<ListBox>
{
public static readonly DependencyProperty IsContinuousProperty = DependencyProperty.Register("IsContinuous",
typeof(bool),
typeof(ListBoxFocusBehavior),
new PropertyMetadata(
false,
(d, e) => ((ListBoxFocusBehavior)d).IsContinuousScroll = (bool)e.NewValue));
/// <summary>
/// Gets or sets a value indicating whether this instance is continuous.
/// </summary>
/// <value>
/// <c>true</c> if this instance is continuous; otherwise, <c>false</c>.
/// </value>
public bool IsContinuous
{
get { return (bool)GetValue(IsContinuousProperty); }
set { SetValue(IsContinuousProperty, value); }
}
/// <summary>
/// Called after the behavior is attached to an AssociatedObject.
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += SelectionChanged;
AssociatedObject.KeyDown += KeyDown;
}
/// <summary>
/// Keys down.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param>
private void KeyDown(object sender, KeyEventArgs e)
{
e.Handled = false;
if (e.Key == Key.Tab && Keyboard.Modifiers == ModifierKeys.None)
{
//forward tab ...
var idx = AssociatedObject.Items.IndexOf(AssociatedObject.SelectedItem);
if (idx < AssociatedObject.Items.Count-1)
{
AssociatedObject.SelectedItem = AssociatedObject.Items[idx + 1];
e.Handled = true;
}
}
if (e.Key == Key.Tab && (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
{
//back tab.
var idx = AssociatedObject.Items.IndexOf(AssociatedObject.SelectedItem);
if (idx > 0)
{
AssociatedObject.SelectedItem = AssociatedObject.Items[idx - 1];
e.Handled = true;
}
}
}
/// <summary>
/// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.SelectionChanged -= SelectionChanged;
AssociatedObject.KeyDown -= KeyDown;
}
/// <summary>
/// Gots the focus.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
private void GotFocus(object sender, RoutedEventArgs e)
{
if (AssociatedObject.SelectedItem == null && AssociatedObject.Items.Any())
{
AssociatedObject.SelectedItem = AssociatedObject.Items.First();
}
}
/// <summary>
/// Selections the changed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
private void SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (AssociatedObject.SelectedItem == null) return;
AssociatedObject.UpdateLayout();
//have to, otherwise the listbox will probably not focus.
Action setFocus = () =>
{
AssociatedObject.UpdateLayout();
AssociatedObject.ScrollIntoView(AssociatedObject.SelectedItem);
//ensure that if the container did not exist yet (virtualized), it gets created.
AssociatedObject.UpdateLayout();
var container =
AssociatedObject.ItemContainerGenerator.ContainerFromItem(
AssociatedObject.SelectedItem) as Control;
if (container != null)
{
container.Focus();
}
};
AssociatedObject.Dispatcher.BeginInvoke(setFocus);
}
}
}

WPF and MDI model

After many years of Windows Forms development, i decided to experiment with WPF. In the company i work for, i have built a great amount of software based on the MDI style and i would like to continue to do so when using WPF.
I know that MDI is not "supported" my WPF and i am trying to find a work around this matter. I also know that i can mimic MDI behavior by the WPF tab control but this is not an optimal solution for me.
Users here, are used to have software with an MDI form and many forms underneath that serve as monitoring different tasks, asynchronously, and being always visible.
Is there any way i can achieve this functionality in WPF without Tab or using 3rd party controls and without some kine of WinForms interop ?
One option is to use the following project:
http://wpfmdi.codeplex.com/
Other option is to make something yourself, which allows for interesting stuff relating to multimonitor behaviour etc..
I have built MDI for WPF using functionality of Popup control. I suggest you do not use common win forms way which based on separate controls, but use MVVM for WPF.
So, each MDI window is Popup which wraps a view model. Application itself is base window which hosts view models and operates with windows via view models.
I provide a real life MDI window sample. Be aware that this is not complete sample, but it is enought to demonstrate some basic conceptions. All necessary classes are custom, so no dependency from the third part components:
<DataTemplate DataType="{x:Type vm:Pane}">
<DataTemplate.Resources>
<ControlTemplate x:Key="uiFreePaneTemplate" TargetType="ContentControl">
<Popup
x:Name="PART_DRAG" HorizontalOffset="{Binding X}" VerticalOffset="{Binding Y}"
IsOpen="{Binding IsOpened}" VerticalAlignment="Top" HorizontalAlignment="Left"
AllowsTransparency="True">
<Border
Width="{Binding Width}" Height="{Binding Height}"
BorderThickness="2,2,2,2" Margin="0" CornerRadius="5"
BorderBrush="{StaticResource WindowBackgroundBrush}"
Background="{StaticResource WindowBackgroundBrush}">
<ContentControl Template="{StaticResource Resizer}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--Pane header-->
<Thumb Grid.Row="0" Width="Auto" Height="21">
<i:Interaction.Triggers>
<i:EventTrigger EventName="DragDelta">
<mvvm:EventToCommand Command="{Binding DragCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Thumb.Template>
<ControlTemplate>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF0C286C" Offset="1"/>
<GradientStop Color="Transparent"/>
</LinearGradientBrush>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Name}" Grid.Column="0" />
<Button Template="{StaticResource CloseButton}"
Grid.Column="1"
Margin="1,1,3,1" />
</Grid>
</ControlTemplate>
</Thumb.Template>
</Thumb>
<Grid Grid.Row="1" Background="{StaticResource ControlBackgroundBrush}">
<!--Pane content-->
<AdornerDecorator>
<ContentPresenter Content="{TemplateBinding Content}" />
</AdornerDecorator>
<ResizeGrip x:Name="WindowResizeGrip"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
IsTabStop="false"/>
</Grid>
</Grid>
</ContentControl>
</Border>
</Popup>
</ControlTemplate>
</DataTemplate.Resources>
<ContentControl x:Name="uiBorder" Content="{Binding Model}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsFree}" Value="True">
<Setter TargetName="uiBorder" Property="ContentControl.Template" Value="{StaticResource uiFreePaneTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
View model:
public class Pane : HideableChildViewModel, IPane
{
private IViewModel _model;
private bool _isFree = true;
private string _name;
private double _coordinateX;
private double _coordinateY;
private double _width = 200.0;
private double _height = 400.0;
private ICommand _closeCommand;
private ICommand _dragCommand;
private ICommand _resizeCommand;
/// <summary>
/// Initializes a new instance of the Pane class.
/// </summary>
/// <param name="parent">The parent view model</param>
/// <param name="parentPropertySelector">Selector of the parent property</param>
/// <param name="model">VM to place within the pane</param>
public Pane(
IViewModel parent,
Expression<Func<object>> parentPropertySelector,
IViewModel model)
: base(parent, parentPropertySelector)
{
this.Model = model;
this._dragCommand = new DragPaneCommand();
this._resizeCommand = new ResizeCommand();
if (model != null && model is ICloseableVM)
{
this._closeCommand = new ClosePaneCommand();
}
else
{
this._closeCommand = new HideCommand();
}
}
#region Properties
/// <summary>
/// Gets or sets VM to place within the pane
/// </summary>
public IViewModel Model
{
get
{
return this._model;
}
set
{
if (this._model != value)
{
this._model = value;
this.RaisePropertyChanged(() => this.Model);
}
}
}
/// <summary>
/// Gets or sets name of the pane
/// </summary>
[LayoutSettings(IsKey = true)]
public string Name
{
get
{
return this._name;
}
set
{
if (this._name != value)
{
this._name = value;
this.RaisePropertyChanged(() => this.Name);
}
}
}
/// <summary>
/// Gets or sets X coordinate
/// </summary>
[LayoutSettings]
public double X
{
get
{
return this._coordinateX;
}
set
{
if (this._coordinateX != value)
{
this._coordinateX = value;
this.RaisePropertyChanged(() => this.X);
}
}
}
/// <summary>
/// Gets or sets Y coordinate
/// </summary>
[LayoutSettings]
public double Y
{
get
{
return this._coordinateY;
}
set
{
if (this._coordinateY != value)
{
this._coordinateY = value;
this.RaisePropertyChanged(() => this.Y);
}
}
}
/// <summary>
/// Gets or sets width
/// </summary>
[LayoutSettings]
public double Width
{
get
{
return this._width;
}
set
{
if (this._width != value)
{
this._width = value;
this.RaisePropertyChanged(() => this.Width);
}
}
}
/// <summary>
/// Gets or sets height
/// </summary>
[LayoutSettings]
public double Height
{
get
{
return this._height;
}
set
{
if (this._height != value)
{
this._height = value;
this.RaisePropertyChanged(() => this.Height);
}
}
}
/// <summary>
/// Gets or sets a value indicating whether pane is free
/// </summary>
public bool IsFree
{
get
{
return this._isFree;
}
set
{
if (this._isFree != value)
{
this._isFree = value;
this.OnIsFreeChanged(this._isFree);
this.RaisePropertyChanged(() => this.IsFree);
}
}
}
#endregion
#region Commands
/// <summary>
/// Gets command for pane closing
/// </summary>
public ICommand CloseCommand
{
get { return this._closeCommand; }
}
/// <summary>
/// Gets command for pane dragging
/// </summary>
public ICommand DragCommand
{
get { return this._dragCommand; }
}
/// <summary>
/// Gets command for pane resize
/// </summary>
public ICommand ResizeCommand
{
get { return this._resizeCommand; }
}
#endregion
private void OnIsFreeChanged(bool isFree)
{
if (!isFree)
{
return;
}
IDockContainer oContainer = ((IChildViewModel)((IChildViewModel)this.Parent).Parent).Parent as IDockContainer;
if (oContainer != null)
{
this.SetParent(oContainer, () => oContainer.FreeItems);
}
}
}

Categories

Resources