Contents
- Microsoft WPF Samples
- Binding to DependencyProperties in your code-behind
- Simple Binding to XML in a ListView
- SumConverter
- Get an IWin32Window reference when using WPF (C#)
- Auto-updating DataGridView
- Access an RTF Document that is compiled into an EXE as an embedded resource
- Binding to Underlying Property of a user control
- FindName Function and Frames
Binding to DependencyProperties in your code-behind
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } public bool IsFlagSet { get { return (bool)GetValue(_isFlagSetProperty); } set { SetValue(_isFlagSetProperty, value); } } public static readonly DependencyProperty _isFlagSetProperty = DependencyProperty.Register("IsFlagSet", typeof(bool), typeof(MainWindow), new FrameworkPropertyMetadata(false)); }
<Window x:Class="CaffeineIT.Blog.XamlCollections.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" DataContext="{Binding RelativeSource={RelativeSource Self}}"> <TextBlock>The flag value is: <TextBlock Text="{Binding Path=IsFlagSet}"/> </TextBlock> </Window>
Most important aspect of this is that the DataContext must point to ‘Self’: {BindingĀ RelativeSource={RelativeSourceĀ Self}}.
Simple Binding to XML in a ListView
XMLFile1.xml
1 <?xml version="1.0" encoding="utf-8" ?>
2 <?xml version="1.0" encoding="utf-8" ?>
3 <Parties>
4 <Party Contact="Jim Shmekel"
5 Qty="1"
6 Amount="55.00"
7 Tot="55.00"/>
8 <Party Contact="Shmi Skywalker"
9 Qty="1"
10 Amount="20.00"
11 Tot="20.00"/>
12 <Party Contact="Jon Ronson"
13 Qty="1"
14 Amount="23.00"
15 Tot="23.00"/>
16 </Parties>
MainWindow.xaml
Note – you could bind directly to myParties – CollectionViewSource is put between myParties and the binding here, and gives extra functionality like sorting.
The key point here is in the ListView:
ItemsSource="{Binding Source={StaticResource myCollectionViewSource},XPath='Party',Mode=TwoWay}"
This is where the ListView is bound to the underlying XML data.
1 <Window x:Class="MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:converters="clr-namespace:WpfApplication2"
5 Title="MainWindow" Height="350" Width="525">
6
7 <Window.Resources>
8 <XmlDataProvider x:Key="myParties" XPath="Parties" Source="XMLFile1.xml" />
9 <CollectionViewSource x:Key="myCollectionViewSource" Source="{StaticResource myParties}" />
10 <converters:SumConverter x:Key="mySumConverter" />
11 </Window.Resources>
12
13 <StackPanel>
14 <ListView x:Name="myListView"
15 HorizontalAlignment="Stretch"
16 ItemsSource="{Binding Source={StaticResource myCollectionViewSource},XPath='Party',Mode=TwoWay}">
17 <ListView.View>
18 <GridView>
19 <GridViewColumn Width="100" DisplayMemberBinding="{Binding XPath='@Contact'}" Header="Contact"/>
20 <GridViewColumn DisplayMemberBinding="{Binding XPath='@Qty'}" Header="Q"/>
21 <GridViewColumn DisplayMemberBinding="{Binding XPath='@Amount'}" Header="Amt"/>
22 <GridViewColumn x:Name="tbTot" Header="Tot">
23 <GridViewColumn.CellTemplate>
24 <DataTemplate>
25 <DockPanel>
26 <TextBox Width="100" Text="{Binding XPath='@Tot'}" />
27 </DockPanel>
28 </DataTemplate>
29 </GridViewColumn.CellTemplate>
30 </GridViewColumn>
31 </GridView>
32 </ListView.View>
33 </ListView>
34
35 <Label Height="22">
36 <Label.Content>
37 <MultiBinding Converter="{StaticResource mySumConverter}">
38 <Binding ElementName="myListView" Path="Items"/>
39 <Binding ElementName="myListView" Path="Items.Count"/>
40 </MultiBinding>
41 </Label.Content>
42 </Label>
43 </StackPanel>
44 </Window>
SumConverter
Imports System.Collections.ObjectModel Imports System.Reflection <ValueConversion(GetType(Object()), GetType(String))> Public Class SumConverter : Implements System.Windows.Data.IMultiValueConverter Public Function Convert(ByVal values() As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IMultiValueConverter.Convert Static lvItems As IList Static lvItem As Xml.XmlElement Dim nVal As Double Convert = 0 lvItems = values(0) If lvItems Is Nothing Then Exit Function For Each lvItem In lvItems 'Debug.Print(lvItem.GetAttribute("Tot")) If Double.TryParse(lvItem.GetAttribute("Tot"), nVal) Then Convert = Convert + nVal End If Next End Function Public Function ConvertBack(ByVal value As Object, ByVal targetTypes() As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object() Implements System.Windows.Data.IMultiValueConverter.ConvertBack ConvertBack = Nothing End Function End Class
Get an IWin32Window reference when using WPF (C#)
Sometimes you need a reference to IWin32Window to use components that are compatible with Windows Forms.
-
To your WPF window, add:
using System.Windows.Forms; using System.Windows.Interop;
-
To your class’s definition add IWin32Window. This denotes that you are implementing the IWin32Window interface:
public partial class MainWindow : Window, System.Windows.Forms.IWin32Window
-
Implement the Handle method, which is needed to complete an IWin32Window interface.
public IntPtr Handle { get { var interopHelper = new WindowInteropHelper(this); return interopHelper.Handle; } }
Auto-updating DataGridView
Public Class party Dim _contact As String Dim _qty As Double Dim _amount As Double Public Delegate Sub _ContactChanged() Public Delegate Sub _QtyChanged() Public Delegate Sub _AmountChanged() Public Event ContactChanged As _ContactChanged Public Event QtyChanged As _QtyChanged Public Event AmountChanged As _AmountChanged Public Sub New(ByVal Contact As String, ByVal Qty As Double, ByVal Amount As Double) Me.Contact = Contact Me.Qty = Qty Me.Amount = Amount End Sub Property Contact As String Get Contact = _contact End Get Set(ByVal value As String) _contact = value RaiseEvent ContactChanged() End Set End Property Property Qty As Double Get Qty = _qty End Get Set(ByVal value As Double) _qty = value RaiseEvent QtyChanged() End Set End Property Property Amount As Double Get Amount = _amount End Get Set(ByVal value As Double) _amount = value RaiseEvent AmountChanged() End Set End Property End Class 'ViewModel Public Class parties : Implements INotifyPropertyChanged Dim _parties As ObservableCollection(Of party) Dim _totalQtyAmount As Double Property Parties As ObservableCollection(Of party) Get Parties = _parties End Get Set(ByVal value As ObservableCollection(Of party)) _parties = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Parties")) End Set End Property Property TotalQtyAmount As Double Get TotalQtyAmount = _totalQtyAmount End Get Set(ByVal value As Double) _totalQtyAmount = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("TotalQtyAmount")) End Set End Property Public Sub New() Parties = New ObservableCollection(Of party) Parties.Add(New party("Bill Jones", 1, 100.0)) Parties.Add(New party("John Armond", 2, 300.0)) Parties.Add(New party("Yasmin LaFont", 1, 100.0)) Parties.Add(New party("Fred Frankstone", 3, 999.0)) Dim i For i = 0 To Parties.Count - 1 AddHandler Parties(i).AmountChanged, AddressOf UpdateTotalQtyAmount AddHandler Parties(i).QtyChanged, AddressOf UpdateTotalQtyAmount AddHandler Parties(i).ContactChanged, AddressOf UpdateTotalQtyAmount Next UpdateTotalQtyAmount() End Sub Private Sub UpdateTotalQtyAmount() TotalQtyAmount = (From tot In Parties Select tot.Amount * tot.Qty).Sum() End Sub Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged Private Sub NotifyPropertyChanged(ByVal info As String) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info)) End Sub End Class
XAML:
1 <StackPanel Grid.Column="1">
2 <StackPanel.DataContext>
3 <me:parties/>
4 </StackPanel.DataContext>
5 <Label Content="Parties" FontWeight="Bold" />
6 <my:DataGrid AutoGenerateColumns="False"
7 x:Name="Aspen_Parties" ItemsSource="{Binding Parties}">
8 <my:DataGrid.Columns>
9 <my:DataGridTextColumn Header="Contact" Binding="{Binding Path=Contact,UpdateSourceTrigger=PropertyChanged}" Width="100">
10 <my:DataGridTextColumn.ElementStyle>
11 <Style TargetType="{x:Type TextBlock}">
12 <Setter Property="TextWrapping" Value="Wrap"/>
13 </Style>
14 </my:DataGridTextColumn.ElementStyle>
15 </my:DataGridTextColumn>
16 <my:DataGridTextColumn Header="Q" Binding="{Binding Path=Qty,UpdateSourceTrigger=PropertyChanged}" />
17 <my:DataGridTextColumn Header="Tot" Binding="{Binding Path=Amount,StringFormat='C',UpdateSourceTrigger=PropertyChanged}"/>
18 </my:DataGrid.Columns>
19 </my:DataGrid>
20
21 <Label Height="22" HorizontalAlignment="Stretch" HorizontalContentAlignment="Right" Content="{Binding Path=TotalQtyAmount}"/>
22 </StackPanel>
Access an RTF Document that is compiled into an EXE as an embedded resource
To access an RTF document and populate a RichTextBox with its contents:
Dim txt As New TextRange(TheRichTextBoxToPopulate.Document.ContentStart, TheRichTextBoxToPopulate.Document.ContentEnd) Dim _assembly As [Assembly] _assembly = [Assembly].GetExecutingAssembly() txt.Load(_assembly.GetManifestResourceStream("WpfApplication1.<filename>.rtf"), System.Windows.DataFormats.Rtf)
Binding to Underlying Property of a user control
1 <UserControl ... x:Name="root"/>
1 <Label x:Name="lblHeader" Content="{Binding Path=Header, ElementName=root}"/>
In code-behind:
Public Shared ReadOnly HeaderProperty As DependencyProperty = _ DependencyProperty.Register("Header", _ GetType(String), _ GetType(ListViewWithHeaderControl), _ New FrameworkPropertyMetadata(New String("Header"), FrameworkPropertyMetadataOptions.AffectsRender)) Public Property Header As String Get Header = GetValue(HeaderProperty) End Get Set(ByVal value As String) SetValue(HeaderProperty, value) End Set End Property
FindName Function and Frames
A window has a FindName function, but it does not search in the content of frames. To access names within frames, do:
Window.GetWindow(Me).FindName("fullReportFrame").Content.FindName("CalculationsFrame").Content.jcData
The Content property should give you the “code-behind” object of the WPF element.