How do I create a XAML binding to a member variable? - c#

I'm new to XAML and data binding. I want to define a GUI control in MainWindow.xaml that gets its data from a member variable in MainWindow.xaml.cs. For simplicity's sake I just made a program that displays a counter as well as a button to increment the counter.
Based on earlier threads I've looked up, I came up with the following code:
MainWindow.xaml.cs
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 XAMLBindingTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private int Counter
{
get { return (int)GetValue(CounterProperty); }
set { SetValue(CounterProperty, value); }
}
public static readonly DependencyProperty CounterProperty =
DependencyProperty.Register("Counter", typeof(int), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
Counter = 0;
InitializeComponent();
}
private void incrementCounter(object sender, RoutedEventArgs e)
{
++Counter;
}
}
}
MainWindow.xaml
<Window x:Class="XAMLBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="140" Width="180">
<Grid>
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock x:Name="txbCounter" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Counter}" VerticalAlignment="Top"/>
<Button x:Name="btnIncrement" Content="Increment" Width="75" Click="incrementCounter"/>
</StackPanel>
</Grid>
</Window>
This example compiles, but the TextBlock isn't showing a counter value. How do I wire the TextBlock to the Counter member in a correct way?

Try adding a "Name" to your window and binding using "ElementName"
<Window x:Class="XAMLBindingTest.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" Name="UI">
<Grid>
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock x:Name="txbCounter" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding ElementName=UI, Path=Counter}" VerticalAlignment="Top"/>
<Button x:Name="btnIncrement" Content="Increment" Width="75" Click="incrementCounter"/>
</StackPanel>
</Grid>
</Window>

If i understood you correctly:
ItemSource="{Binding Path=TestData, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type common:LayoutAwarePage}}}"
TestData is property of type ObservableCollection declared in .xaml.cs file. ItemSource - is a example property you want bind to.
UPD2:
<ItemsControl ItemSource="{Binding Path=TestData, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type common:LayoutAwarePage}}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Related

WPF Combobox event does not fire (using MVVM and Expression.Blend)

I am really fairly new to WPF and have just wrapped my head around MVVM / Expression.Blend.
I am trying to use the Combobox "SelectedIndexChanged" event with InvokeCommandAction, binding to a command specified in the ViewModel.
However, the code in the command is never executed (the value myvalue is never updated).
What am I doing wrong here?
XAML:
<UserControl x:Class="GDX.UI.Views.AnalyseView"
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:i1="http://schemas.microsoft.com/xaml/behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:local="clr-namespace:GDX.UI.Views"
mc:Ignorable="d"
Height="720" Width="1210">
<Control.Resources>
<ResourceDictionary Source="pack://application:,,,/GDX.UI;component/ResourceDictionary/ResourceDictionary.xaml"/>
</Control.Resources>
<materialDesign:Card Margin="15,15,15,15" Grid.Column ="0" Grid.Row="0" Grid.RowSpan="6" Grid.ColumnSpan="2">
<ScrollViewer Grid.Row="0" Grid.RowSpan="5" Grid.Column="0" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Hidden">
<ItemsControl ItemsSource="{Binding buildingComponents}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="10">
<TextBlock Margin="10" Text="{Binding Path=UIName}" FontWeight="Bold"/>
<ComboBox
ItemsSource="{Binding Path=ConstructionOptions}"
SelectedItem="{Binding Path=Construction}"
HorizontalAlignment="Center"
Style="{StaticResource MaterialDesignOutlinedComboBox}"
Width="256"
Height="50"
BorderBrush="Red"
materialDesign:HintAssist.Hint="Baukonstruktion">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedIndexChanged">
<i:InvokeCommandAction Command="{Binding SetBuildingComponentConstruction}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</materialDesign:Card>
ViewModel:
using GDX.IO.Schemas;
using GDX.IO.Statics;
using GDX.MVVM;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace GDX.ViewModel.ViewModels
{
public class AnalyseViewModel : BaseViewModel
{
public ObservableCollection<BuildingComponent> buildingComponents { get; set; }
public double myvalue { get; set; }
public ICommand SetBuildingComponentConstruction { get; set; }
public AnalyseViewModel()
{
this.buildingComponents = new ObservableCollection<BuildingComponent>();
if (Building.BuildingComponents.Count != 0) //if contains elements
{
foreach (BuildingComponent bcomp in Building.BuildingComponents)
{
this.buildingComponents.Add(bcomp);
}
}
this.SetBuildingComponentConstruction = new RelayCommand(this.setBuildingComponentConstruction);
this.myvalue = 0;
}
public void setBuildingComponentConstruction()
{
myvalue += 1;
}
}
}
Looks like the SetBuildingComponentConstruction method is defined on AnalyseViewModel, but where you are binding in the itemstemplate the datacontext would be a BuildingComponent. You may have to "walk" up to the datacontext of your UserControl.
How do I use WPF bindings with RelativeSource?
Looking at the XAML Binding Failures tab in VS while debugging may also provide you with some direction.
Try
Command="{Binding DataContext.SetBuildingComponentConstruction,
RelativeSource={RelativeSource AncestorType=ComboBox}}"

ViewModel issue

I need pop up a window which takes time. The button is in Pressed state until the new window is opened. Hence I want to add a wait indicator over the UI window after I click the button and before the the window opens. The code of ViewModel is correct because I referred to a sample code. But why there is no response after I click the button.
The project file URL
https://supportcenter.devexpress.com/attachment/file/5268961b-ce35-4e40-b7c1-e33bffab902b
MainWindow:
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;
using DevExpress.Xpf.Core;
namespace WaitIndicatorDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : DXWindow
{
public MainWindow()
{
InitializeComponent();
vm = new MainVM();
DataContext = vm;
}
MainVM vm;
private void buttonShow_Click(object sender, RoutedEventArgs e)
{
vm.IsBusy = !vm.IsBusy;
}
}
}
ViewMode:
using DevExpress.Mvvm;
namespace WaitIndicatorDemo
{
public class MainVM
{
private readonly ISplashScreenService _waitIndicatorService;
public virtual bool IsBusy { get; set; }
public MainVM()
{
_waitIndicatorService =
ServiceContainer.Default.GetService<ISplashScreenService>("WaitIndicatorService");
}
protected void OnIsBusyChanged()
{
if (IsBusy)
_waitIndicatorService.ShowSplashScreen();
else
_waitIndicatorService.HideSplashScreen();
}
}
}
Below is the XAML, the comment ones are the original sample code. The checkbox bind to IsBusy. The indicator pop up when the checkbox is checked. I now want to pop up after press the button.
<dx:DXWindow x:Class="WaitIndicatorDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:waitIndicatorDemo="clr-namespace:WaitIndicatorDemo"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
WindowStartupLocation="CenterScreen" SnapsToDevicePixels="True"
Title="MainWindow" Height="350" Width="525">
<!--DataContext="{dxmvvm:ViewModelSource Type=waitIndicatorDemo:MainVM}"-->
<!--Title="MainWindow" Height="350" Width="525">-->
<Grid Margin="10">
<!--<dxe:CheckEdit Content="Is Busy" IsChecked="{Binding IsBusy}"
VerticalAlignment="Top" HorizontalAlignment="Left" />
<Button Content="Button1" IsEnabled ="{Binding IsBusy, Converter={dxmvvm:BooleanNegationConverter}}"
VerticalAlignment="Top" HorizontalAlignment="Center" Click="Button_Click"/>
<Button Content="Button2" IsEnabled="{Binding IsBusy, Converter={dxmvvm:BooleanNegationConverter}}"
VerticalAlignment="Top" HorizontalAlignment="Right"/>-->
<Button x:Name="buttonShow" Content="Show" HorizontalAlignment="Left" Height="35" Margin="50,70,0,0" VerticalAlignment="Top" Width="75" Click="buttonShow_Click" />
</Grid>
</dx:DXWindow>
You have a few mistakes in your code sample :
1- The method OnIsBusyChanged in your ViewModel is never called.
2- Your XAML doesn't declare any ISplashScreenService object in the Window behaviors, like a DXSplashScreenService for instance.
Here's how you can fix both of those issues.
First, fix the ViewModel.
public class MainVM
{
private readonly ISplashScreenService _waitIndicatorService;
private bool _isBusy;
public virtual bool IsBusy
{
get
{
return _isBusy;
}
set
{
_isBusy = value;
OnIsBusyChanged();
}
}
public MainVM()
{
_waitIndicatorService =
ServiceContainer.Default.GetService<ISplashScreenService>("WaitIndicatorService");
}
protected void OnIsBusyChanged()
{
_waitIndicatorService.SetSplashScreenState("Doing some work...");
if (IsBusy)
_waitIndicatorService.ShowSplashScreen();
else
_waitIndicatorService.HideSplashScreen();
}
}
Then, your XAML.
<dx:DXWindow x:Class="WaitIndicatorDemo.MainWindow"
<!-- ... -->
Title="MainWindow" Height="350" Width="525">
<dxmvvm:Interaction.Behaviors>
<dx:DXSplashScreenService x:Name="WaitIndicatorService">
<dx:DXSplashScreenService.ViewTemplate>
<DataTemplate>
<Grid>
<Border Background="LightGray" CornerRadius="5">
<Border BorderBrush="#FF0072C6" BorderThickness="1" Margin="15" CornerRadius="5">
<Grid>
<ProgressBar BorderThickness="0" Value="{Binding Progress}" Maximum="{Binding MaxProgress}" IsIndeterminate="{Binding IsIndeterminate}" Height="12" />
<TextBlock Text="{Binding State, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</Border>
</Grid>
</DataTemplate>
</dx:DXSplashScreenService.ViewTemplate>
</dx:DXSplashScreenService>
</dxmvvm:Interaction.Behaviors>
<Grid Margin="10">
<!-- ... -->
</Grid>
</dx:DXWindow>
This code was mainly taken from the How to: Use DxSplashScreenService sample.

C# WPF application using data binding, data templates and observable collection

I am making a program in C# WPF using data binding, data templates and observable collection. I am basing my application on the Data Binding Demo from http://msdn.microsoft.com/en-us/library/vstudio/ms771319(v=vs.90).aspx. For some reason I cannot make my program display any data from binding. Debugging tells me that my Records class collection works but on this line:
records_collection_db = (CollectionViewSource)(this.Resources["records_collection_db"]);
my 'records_collection_db' variable in null whereas it should be holding some data. I suspect that that my CollectionViewSource in xaml line is set incorrectly but I don't really know how to fix it. It is my first program in WPF and so I don't have much experience on the subject. At this moment the only visible difference between my code and the one from sample is that my initial window is... a where in the demo it an
Code (or at least shortened version of it):
Record class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace WpfApplication1
{
public class Record : INotifyPropertyChanged
{
private int Lp;
private string group;
public event PropertyChangedEventHandler PropertyChanged;
public int _Lp
{
get { return this.Lp; }
set { this.Lp = value; OnPropertyChanged("_Lp"); }
}
public string _group
{
get { return this.group; }
set { this.group = value; OnPropertyChanged("_group"); }
}
public Record(int Lp, string group)
{
this.Lp = Lp;
this.group = group;
}
protected void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
Initial window
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Configuration;
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 WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var newWindow1 = new Audyt_window();
newWindow1.Show();
}
}
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:WpfApplication1"
xmlns:System="clr-namespace:System;assembly=Mscorlib"
Title="MainWindow" Height="350" Width="525"
WindowStartupLocation="CenterScreen"
>
<Window.Resources>
<Style x:Key="text_style" TargetType="TextBlock">
<Setter Property="Foreground" Value="#333333" />
</Style>
</Window.Resources>
<Grid>
<Button Content="Start" HorizontalAlignment="Left" Margin="36,36,0,0" VerticalAlignment="Top" Width="178" Height="93" Click="Button_Click"/>
<Button Content="Zamknij" HorizontalAlignment="Left" Margin="202,223,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
<Button Content="Rekordy" HorizontalAlignment="Left" Margin="318,56,0,0" VerticalAlignment="Top" Width="108" Height="52" Click="Button_Click_2" />
<Button Content="Dodaj" HorizontalAlignment="Left" Margin="351,157,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_3"/>
</Grid>
</Window>
Operational window
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.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.ComponentModel;
namespace WpfApplication1
{
public partial class Audyt_window : Window
{
CollectionViewSource records_collection;
private ObservableCollection<Record> records = new ObservableCollection<Record>();
public ObservableCollection<Record> Records
{
get { return this.records; }
set { this.records = value; }
}
public Audyt_window()
{
load_temp_data();
InitializeComponent();
records_collection = (CollectionViewSource)(this.Resources["records_collection"]);
}
private void load_temp_data()
{
Record rek1 = new Record(601, "Gr1", "Pro1", "Pyt1", 600001, "Kat1", false, false);
Record rek2 = new Record(602, "Gr2", "Pro2", "Pyt2", 600002, "Kat2", false, false);
Record rek3 = new Record(603, "Gr3", "Pro3", "Pyt3", 600003, "Kat3", false, false);
this.Records.Add(rek1);
this.Records.Add(rek2);
this.Records.Add(rek3);
}
}
}
<Window x:Class="WpfApplication1.Audyt_window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Audyt"
xmlns:src="clr-namespace:WpfApplication1"
ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
>
<Window.Resources>
<CollectionViewSource Source="{Binding Source={x:Static Application.Current}, Path=Records}" x:Key="records_collection" />
<Style x:Key="text_style" TargetType="TextBlock">
<Setter Property="Foreground" Value="#333333" />
</Style>
<DataTemplate x:Key="Records_Template" DataType="{x:Type src:Record}">
<Border BorderThickness="2" BorderBrush="Navy" Padding="7" Name="Record_List_Border" Margin="3" Width="345">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Background="Aqua" Grid.Row="0" Grid.Column="0"
Name="textblock_Lp"
Style="{StaticResource text_style}"
Text="Lp: "
>
</TextBlock>
<TextBlock Background="Azure" Grid.Row="0" Grid.Column="1"
Name="datablock_Lp"
Style="{StaticResource text_style}"
Text="{Binding Path=_Lp}"
>
</TextBlock>
<TextBlock Background="Aqua" Grid.Row="0" Grid.Column="2"
Name="datablock_group"
Style="{StaticResource text_style}"
Text="{Binding Path=_group}"
>
</TextBlock>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
<Border Padding="10">
<Grid>
<ListBox Name="Hits_View_List" HorizontalAlignment="Left" VerticalAlignment="Top"
Height="525" Width="400" Margin="420,0,0,0"
BorderThickness="2" BorderBrush="DimGray"
ItemsSource="{Binding Source={StaticResource records_collection}}"
>
</ListBox>
</Grid>
</Border>
</Window>
In your Audyt_window you set the source of your binding of the CollectionViewSource to {x:Static Application.Current}, but the Records ObservableCollection is declared inside your Audyt_window
Change:
<CollectionViewSource Source="{Binding Source={x:Static Application.Current}, Path=Records}" x:Key="records_collection" />
To
<CollectionViewSource Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=Records}" x:Key="records_collection" />
And it should work I think.
you Name your collectionviewsource
x:Key="records_collection"
and you are searching for records_collection_db... that cant match
records_collection_db = (CollectionViewSource)(this.Resources["records_collection_db"]);
Change the Key or Change the string to the right name

Upadate TreeView From Class .cs

Good morning for all;
I have a TreeView in my Window WPF, I use DataBinding to cover my TreeView.
Now I have another Class MyDesign.cs , and I want to upade the itms of my TreeView from this Class.
here My code:
MainWindow.xaml:
<Window x:Class="TreeViewAndDataBanding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:TreeViewAndDataBanding"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ContextMenu x:Key="MyDesignContextMenu">
<MenuItem Header="Paste" Command="{x:Static ApplicationCommands.Paste}"/>
<MenuItem Header="Search" Command="{x:Static self:MyDesign.Search}"/>
</ContextMenu>
<self:test x:Key="test"/>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24*"/>
<ColumnDefinition Width="23*"/>
</Grid.ColumnDefinitions>
<TreeView x:Name="MyToolBox" ItemsSource="{StaticResource test}" Grid.Column="1" >
<TreeView.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="All Cars">
<TreeViewItem Header="{Binding Path= Voiture}">
<TreeViewItem Header="{Binding Path=Vitesse}"></TreeViewItem>
</TreeViewItem>
</TreeViewItem>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<s:MyDesign Focusable="true" x:Name="MyDesigner"
Background="{StaticResource WindowBackgroundBrush}"
Margin="10" FocusVisualStyle="{x:Null}"
ContextMenu="{StaticResource MyDesignContextMenu}" Grid.Coulum="0"/>
</Grid>
</Window>
MenuItem.cs
namespace TreeViewAndDataBanding
{
public class MenuItem
{
private string _Voiture;
private string _Vitesse;
public MenuItem( string Voiture,string Vitesse)
{
this._Voiture = Voiture;
this._Vitesse = Vitesse;
}
public string Voiture
{
get { return _Voiture; }
}
public string Vitesse
{
get { return _Vitesse; }
}
}
}
test.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace TreeViewAndDataBanding
{
public class test : ObservableCollection<MenuItem>
{
public test()
{
Add(new MenuItem("Rapide", "Ferrari F430"));
}
}
}
And here My class MyDesign.Command.Cs, I want to be able to update my treeView in this Class (in method Search)
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace TreeViewAndDataBanding
{
public class MyDesign
{
public static RoutedCommand Search = new RoutedCommand();
public MyDesign()
{
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, Paste_Executed));
this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, Search_Executed));
}
private void Search_Executed(object sender, ExecutedRoutedEventArgs e)
{
// d'ici je veux modifier mon TreeView
/******************************************************************************************/
/****** ici je veux modifier et mettre a jour mon Treeview dans l'interface *************/
/****************************************************************************************/
}
private void Paste_Executed(object sender, ExecutedRoutedEventArgs e)
{
}
}
}
Can You help me please,?? any ideas??
Doing this MVVM style is much cleaner, easier to maintain, and makes WPF make a lot more sense. An example (I've renamed a few things as my French is well. non-existent)
Create a ViewModel:
public class ViewModel {
public ObservableCollection<CarType> CarTypes { get; private set; }
public ViewModel() {
CarsTypes = new ObservableCollection<CarType>();
var sportsCars = new CarType("Sports cars");
sportscars.Cars.Add(new Car() { Make = "Ferrari", Model = "F430" });
CarTypes.Add(sportsCars);
}
}
And your View:
<Window ...
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Window.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding Cars}" DataType="{x:Type local:CarType}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:Car}">
<StackPanel>
<TextBlock Text="{Binding Make}"/>
<TextBlock> - </TextBlock>
<TextBlock Text="{Binding Model}"/>
</DataTemplate>
</Window.Resources>
<TreeView ItemsSource="{Binding CarTypes}"/>
</Window>
Please note that I typed above directly into SO, so I haven't compiled it. I may contains a few errors. But as you can see, using MVVM, this is very little code.
Now you can just add new instances to the Collection on the ViewModel, and your UI will update. Commands can be implemented on the ViewModel using RelayCommands.

how to make user control return its item?

I have a user control with a canvas on it. I want to be able to reference the canvas element, but I can't.
I tried to create a method in the code-behind to return the canvas, but it doesn't work, because when I need to use it I must create a new instance of the user control and that will contain an empty canvas. I need the canvas that's in the current showing window.
Here is the method that I have created to return the canvas:
public DesignerCanvas ret()
{
return this.MyDesigner;
}
Here is the XAML:
<UserControl x:Class="DiagramDesigner.WindowsUserControl"
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:s="clr-namespace:DiagramDesigner"
xmlns:usercontrols="clr-namespace:DiagramDesigner"
xmlns:c="clr-namespace:DiagramDesigner.Controls"
mc:Ignorable="d"
d:DesignHeight="700" d:DesignWidth="1000">
<UserControl.Resources>
<ContextMenu x:Key="DesignerCanvasContextMenu" >
<MenuItem Header="Paste" Command="{x:Static ApplicationCommands.Paste}">
<MenuItem.Icon>
<Image Source="Resources/Images/Paste.png" Width="16"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Select All" Command="{x:Static s:DesignerCanvas.SelectAll}"/>
</ContextMenu>
</UserControl.Resources>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- Toolbox -->
<StackPanel Grid.Column="0" Margin="0,0,5,0" >
<usercontrols:UserControl1></usercontrols:UserControl1>
</StackPanel>
<!-- GridSplitter -->
<GridSplitter Focusable="False" Width="2" Background="LightGray"
VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
<!-- Designer -->
<GroupBox Header="Diagram" Grid.Column="1" Margin="3,0,0,0">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<s:DesignerCanvas Focusable="true" x:Name="MyDesigner"
Background="{StaticResource WindowBackgroundBrush}"
Margin="10" FocusVisualStyle="{x:Null}"
ContextMenu="{StaticResource DesignerCanvasContextMenu}"/>
</ScrollViewer>
</GroupBox>
</Grid>
</Grid>
</UserControl>
and here is my usercontrol.xaml.cs code
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 DiagramDesigner
{
/// <summary>
/// Interaction logic for WindowsUserControl.xaml
/// </summary>
public partial class WindowsUserControl : UserControl
{
public WindowsUserControl()
{
InitializeComponent();
}
public DesignerCanvas ret()
{
return this.MyDesigner;
}
}
}
the mainwindow.xaml code
<Window x:Class="DiagramDesigner.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:DiagramDesigner"
xmlns:c="clr-namespace:DiagramDesigner.Controls"
xmlns:usercontrols="clr-namespace:DiagramDesigner"
WindowStartupLocation="CenterScreen" WindowState="Maximized"
Title="GEN Diagram Designer"
Height="700" Width="1000" Icon="Resources/Images/coollogo_com-61024358.png">
<Window.Resources>
<ContextMenu x:Key="DesignerCanvasContextMenu">
<MenuItem Header="Paste" Command="{x:Static ApplicationCommands.Paste}">
<MenuItem.Icon>
<Image Source="Resources/Images/Paste.png" Width="16"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Select All" Command="{x:Static s:DesignerCanvas.SelectAll}"/>
</ContextMenu>
</Window.Resources>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentControl Content="{StaticResource MyToolbar}"/>
<Button Margin="776.346,40.022,75.653,39.977" Click="Button_Click_1" Width="120" Height="40" >Generate Code</Button>
<Grid Grid.Row="1">
<usercontrols:WindowsUserControl Loaded="WindowsUserControl_Loaded">
</usercontrols:WindowsUserControl>
</Grid>
</Grid>
</Window>
my mainwindow.xaml.cs code
using System.Windows;
using System.Collections.Generic;
using System.Xml;
using System.Linq;
namespace DiagramDesigner
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
XmlDocument doc = new XmlDocument();
XmlElement elem = doc.CreateElement("code");
doc.AppendChild(elem);
List<DesignerItem> L = new List<DesignerItem>();
foreach (DesignerItem d in ***)
{
L.Add(d);
}
var orderedItems = L.OrderBy(item => DesignerCanvas.GetTop(item)).ToList();
foreach (DesignerItem d in orderedItems)
{
XmlNode ChildNode = doc.ImportNode(d.s.code(), true);
doc.FirstChild.AppendChild(ChildNode);
}
doc.Save(#"D:\code.xml");
}
private void WindowsUserControl_Loaded(object sender, RoutedEventArgs e)
{
}
}
}
in the mainwindow.xaml.cs
the first for each * here where i want to get my canvas
Give your control a name:
<usercontrols:WindowsUserControl Loaded="WindowsUserControl_Loaded" x:Name="someName" />
Then just reference the control using that name:
private void WindowsUserControl_Loaded(object sender, RoutedEventArgs e)
{
var theCanvasFromTheUserControl = someName.ret();
// now do something with theCanvasFromTheUserControl
}

Categories

Resources