Binding user control from parent datacontex WPF - wpf

Im trying to bind/link a datagrid from my main window
MainForm:
<dx:DXWindow
x:Class="LicenceManagerWPF.Forms.frmCustomerLicense"
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"
dx:ThemeManager.ThemeName="Office2016"
xmlns:ctr="clr-namespace:LicenceManagerWPF.Controls"
Title="CustomerLicence" Height="800" Width="1000"
WindowStartupLocation="CenterScreen" Loaded="DXWindow_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition MinHeight="200" Height="200*"/>
<RowDefinition Height="200*"/>
<RowDefinition MinHeight="25" Height="25"/>
</Grid.RowDefinitions>
<StackPanel x:Name="Stack_Top" Orientation="Horizontal" Grid.Row="0" >
<dx:SimpleButton x:Name="btnRefresh" Style="{StaticResource ResourceKey=BtnSmall}" ToolTip="Refresh Licenses" Glyph="{dx:DXImage Image=Refresh_32x32.png}" Content="Resfresh" />
<dx:SimpleButton x:Name="btndNew" Style="{StaticResource ResourceKey=BtnSmall}" ToolTip="New License" Glyph="{dx:DXImage Image=New_32x32.png}" Content="New Customer" />
<dx:SimpleButton x:Name="btnDelete" Style="{StaticResource ResourceKey=BtnSmall}" ToolTip="Delete Licence" Content="Delete" Glyph="{dx:DXImage Image=Cancel_32x32.png}"/>
<dx:SimpleButton x:Name="btnEdit" Style="{StaticResource ResourceKey=BtnSmall}" ToolTip="Edit Customer" Glyph="{dx:DXImage Image=EditContact_32x32.png}" />
<TextBlock Text="Customer: " FontSize="20" Margin="5"/>
<TextBlock Text="{Binding Customer.Name}" FontSize="20"/>
</StackPanel>
<ctr:Licences TblLicenses ="{Binding LicensesTable}" Grid.Row="1">
</ctr:Licences>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ctr:LicenseDetail x:Name="ct_LicenseDetail" Grid.Column="0"/>
<ctr:LicenceLog x:Name="ct_LicenseLog" Grid.Column="1"/>
</Grid>
</Grid>
I created this control:
<UserControl x:Class="LicenceManagerWPF.Controls.Licences"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="500"
x:Name="ctrl_Licenses">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Licence List" Grid.Row="0" FontSize="22" Margin="10" TextAlignment="Left" VerticalAlignment="Center" />
<dxg:GridControl x:Name="grdLicences" ItemsSource="{Binding Path=TblLicenses,ElementName=ctrl_Licenses}" Grid.Row="1"/>
</Grid>
I asaigned the control in one row of the grid in the main window.
The main window is linked(data context) to one class that has this methods
private DataTable GetLicensesTable()
{
var dt = new DataTable();
dt.Columns.AddRange(new DataColumn []{
new DataColumn("SerialNumber",typeof(string)),
new DataColumn("Product",typeof(string)),
new DataColumn("Status",typeof(string)),
new DataColumn("ActivationMode",typeof(string)),
new DataColumn("MaxComputers", typeof(int)),
new DataColumn("NumActive",typeof(int)),
new DataColumn("Description",typeof(string))
});
_Licenses.ForEach((x) => {
var rw = dt.NewRow();
rw["SerialNumber"] = x.SerialNumber;
rw["Product"] = x.Product.Name;
rw["Status"] = x.Status;
rw["ActivationMode"] = Enum.GetName(typeof(ActivationModeEnum), x.ActivationMode); //x.ActivationMode;
rw["MaxComputers"] = x.MaxComputers;
rw["NumActive"] = Activated(x.Product.ProductId);
rw["Description"] = x.Description;
dt.Rows.Add(rw);
});
return dt;
}
public DataTable LicensesTable{
get { return GetLicensesTable(); }
}
what i want is to display the table in the grid that is in the usercontrol.
It is posible?
I tryed this in the code behind my main window:
private void DXWindow_Loaded(object sender, RoutedEventArgs e)
{
if (_CustomerLicense != null)
{
this.DataContext = _CustomerLicense;
this.ct_LicensesList.grdLicences.ItemsSource = _CustomerLicense.LicensesTable();
}
else
{
this.DataContext = _CustomerLicense.LicensesTable();
}
}
it says that tblLicenses is not reconized or not accesible.
Runnin the part of the code behin it works but i think its incorrect the way that im using the control.
Regards

Try this:
<dxg:GridControl x:Name="grdLicences" ItemsSource="{Binding Path=DataContext.LicensesTable, RelativeSource={RelativeSource AncestorType=Window}}" Grid.Row="1"/>
It should work provided that the DataContext of the window has a LicensesTable property.

Related

WPF - Windows Media Import Importable Item List View Data Binding

I am using the Windows Media Import API in a WPF Application using Microsoft Docs import-media-from-a-device as an example. I have nearly got it working now but have yet to get the data binding working to provide the list of importable items so any help with this would be much appreciated. The source code can be downloaded here.
Main Window XAML
enter<Window x:Class="ImportProofOfConcept.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ImportProofOfConcept"
mc:Ignorable="d"
Title="Media Import" Height="450" Width="800" Loaded="Window_Loaded">
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.ColumnSpan="3">
<Label Content="Select the required source to import photos and videos from and then select the required files and click OK."/>
<Label Content="Source:"/>
<ComboBox x:Name="CboSources" SelectionChanged="CboSources_SelectionChanged"/>
<Label Content="Files:"/>
</StackPanel>
<ListView Grid.Row="1" Grid.ColumnSpan="3" MinHeight="10" VerticalAlignment="Stretch" x:Name="fileListView"
HorizontalAlignment="Left" Margin="10,11,0,21"
Width="756"
BorderBrush="#FF858585"
BorderThickness="1"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.05*"/>
<ColumnDefinition Width="0.20*"/>
<ColumnDefinition Width="0.75*"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" IsChecked="{Binding IsSelected, Mode=TwoWay}" />
<Image Grid.Column="1" Source="{Binding Thumbnail}" Width="120" Height="120" Stretch="Uniform"/>
<TextBlock Grid.Column="2" Text="{Binding Name}" VerticalAlignment="Center" Margin="10,0"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Grid.Row="2" Grid.Column="1" Click="ButtonOK_Click" IsDefault="True" Margin="6">OK</Button>
<Button Grid.Row="2" Grid.Column="2" Click="ButtonCancel_Click" IsCancel="True" Margin="6">Cancel</Button>
<ProgressBar Grid.Row="3" Grid.ColumnSpan="3" x:Name="progressBar" SmallChange="0.01" LargeChange="0.1" Maximum="1"/>
</Grid>
Code Behind
private async void FindItems()
{
this.cts = new CancellationTokenSource();
try
{
this.importSession = this.importSource.CreateImportSession();
// Progress handler for FindItemsAsync
var progress = new Progress<uint>((result) =>
{
System.Diagnostics.Debug.WriteLine(String.Format("Found {0} Files", result.ToString()));
});
this.itemsResult =
await this.importSession.FindItemsAsync(PhotoImportContentTypeFilter.ImagesAndVideos, PhotoImportItemSelectionMode.SelectAll)
.AsTask(this.cts.Token, progress);
// GeneratorIncrementalLoadingClass is used to incrementally load items in the Listview view including thumbnails
this.itemsToImport = new GeneratorIncrementalLoadingClass<ImportableItemWrapper>(this.itemsResult.TotalCount,
(int index) =>
{
return new ImportableItemWrapper(this.itemsResult.FoundItems[index]);
});
// Set the items source for the ListView control
this.fileListView.ItemsSource = this.itemsToImport;
// Log the find results
if (this.itemsResult != null)
{
var findResultProperties = new System.Text.StringBuilder();
findResultProperties.AppendLine(String.Format("Photos\t\t\t : {0} \t\t Selected Photos\t\t: {1}", itemsResult.PhotosCount, itemsResult.SelectedPhotosCount));
findResultProperties.AppendLine(String.Format("Videos\t\t\t : {0} \t\t Selected Videos\t\t: {1}", itemsResult.VideosCount, itemsResult.SelectedVideosCount));
findResultProperties.AppendLine(String.Format("SideCars\t\t : {0} \t\t Selected Sidecars\t: {1}", itemsResult.SidecarsCount, itemsResult.SelectedSidecarsCount));
findResultProperties.AppendLine(String.Format("Siblings\t\t\t : {0} \t\t Selected Sibilings\t: {1} ", itemsResult.SiblingsCount, itemsResult.SelectedSiblingsCount));
findResultProperties.AppendLine(String.Format("Total Items Items\t : {0} \t\t Selected TotalCount \t: {1}", itemsResult.TotalCount, itemsResult.SelectedTotalCount));
System.Diagnostics.Debug.WriteLine(findResultProperties.ToString());
}
if (this.itemsResult.HasSucceeded)
{
// Update UI to indicate success
System.Diagnostics.Debug.WriteLine("FindItemsAsync succeeded.");
}
else
{
// Update UI to indicate that the operation did not complete
System.Diagnostics.Debug.WriteLine("FindItemsAsync did not succeed or was not completed.");
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Photo import find items operation failed. " + ex.Message);
}
this.cts = null;
}
Remove "ImportableItem" from the binding paths in the XAML markup:
<ListView Grid.Row="1" Grid.ColumnSpan="3" MinHeight="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="LstItems">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.05*"/>
<ColumnDefinition Width="0.20*"/>
<ColumnDefinition Width="0.75*"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" IsChecked="{Binding IsSelected, Mode=TwoWay}" Click="CheckBox_Click"/>
<TextBlock Grid.Column="2" Text="{Binding Name}" VerticalAlignment="Center" Margin="10,0"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When it comes to displaying the thumbnail in an Image element, you need to convert the returned IRandomAccessStreamReference:
Bind XAML Image to IRandomAccessStreamReference

Update binded child wpf when parent change wpf

Im using several controls in my main window.
one grid at top that has a list of licenses and i want to display the information of the license each time i change the selection of the grid
MainWindow:
<dx:DXWindow
x:Class="LicenceManagerWPF.Forms.frmCustomerLicense"
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"
dx:ThemeManager.ThemeName="Office2016"
xmlns:ctr="clr-namespace:LicenceManagerWPF.Controls"
Title="CustomerLicence" Height="800" Width="1000"
WindowStartupLocation="CenterScreen" Loaded="DXWindow_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition MinHeight="200" Height="200*"/>
<RowDefinition Height="200*"/>
<RowDefinition MinHeight="25" Height="25"/>
</Grid.RowDefinitions>
<StackPanel x:Name="Stack_Top" Orientation="Horizontal" Grid.Row="0" >
<dx:SimpleButton x:Name="btnRefresh" Style="{StaticResource ResourceKey=BtnSmall}" ToolTip="Refresh Licenses" Glyph="{dx:DXImage Image=Refresh_32x32.png}" Content="Resfresh" />
<dx:SimpleButton x:Name="btndNew" Style="{StaticResource ResourceKey=BtnSmall}" ToolTip="New License" Glyph="{dx:DXImage Image=New_32x32.png}" Content="New Customer" />
<dx:SimpleButton x:Name="btnDelete" Style="{StaticResource ResourceKey=BtnSmall}" ToolTip="Delete Licence" Content="Delete" Glyph="{dx:DXImage Image=Cancel_32x32.png}"/>
<dx:SimpleButton x:Name="btnEdit" Style="{StaticResource ResourceKey=BtnSmall}" ToolTip="Edit Customer" Glyph="{dx:DXImage Image=EditContact_32x32.png}" />
<TextBlock Text="Customer: " FontSize="20" Margin="5"/>
<TextBlock Text="{Binding Customer.Name}" Margin="5" FontSize="20"/>
</StackPanel>
<ctr:Licences x:Name="grdLicenses" Grid.Row="1">
</ctr:Licences>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ctr:LicenseDetail x:Name="ct_LicenseDetail" Grid.Column="0"/>
<ctr:LicenceLog x:Name="ct_LicenseLog" Grid.Column="1"/>
</Grid>
</Grid>
The grid is ctr_Licenses and the other control is LicenseDetail which should show the information of the license selected, this is the licenseDetail control:
<UserControl
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:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" x:Class="LicenceManagerWPF.Controls.LicenseDetail"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="600" x:Name="ctrl_LicenseDetail" >
<UserControl.Resources>
<Style x:Key="SmallMargin" TargetType="FrameworkElement">
<Setter Property="Margin" Value="5"/>
</Style>
<Style x:Key="TabMargin" TargetType="FrameworkElement" >
<Setter Property="Margin" Value="2.5"/>
</Style>
<Style x:Key="SmalllMarginTextBlock" BasedOn="{StaticResource SmallMargin}" TargetType="{x:Type TextBlock}">
</Style>
<Style x:Key="SmallMarginDropDown" BasedOn="{StaticResource SmallMargin }" TargetType="dx:DropDownButton" >
</Style>
<Style x:Key="SmallMarginText" BasedOn="{StaticResource SmallMargin}" TargetType="TextBox">
</Style>
<Style x:Key="ckkStyle" TargetType="dxe:CheckEdit" BasedOn="{StaticResource TabMargin}">
<Setter Property="IsReadOnly" Value="True"/>
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30"/>
<RowDefinition Height="100*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="License Detail" FontSize="16" Grid.ColumnSpan="2" VerticalAlignment="Center" Margin="10" Grid.Row="0" />
<TextBlock Text="Serial Number:" Grid.Column="0" Grid.Row="1" Style="{StaticResource ResourceKey=SmalllMarginTextBlock}"/>
<TextBlock Text="{Binding Path=DataContext.SelectedLicense.SerialNumber, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType=Window}}" x:Name="txtSerialNum" Grid.Column="1" Grid.Row="1" Style="{StaticResource ResourceKey=SmalllMarginTextBlock}"/>
<TextBlock Text="Product:" Grid.Column="0" Grid.Row="2" Style="{StaticResource ResourceKey=SmalllMarginTextBlock}" />
<StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="1">
<dx:DropDownButton x:Name="dropDownButton" Width="180" Content="Product" Style="{StaticResource SmallMarginDropDown}">
</dx:DropDownButton>
<TextBlock Text="Status:" Style="{StaticResource SmalllMarginTextBlock}" />
<TextBlock Text="" Width="150" Style="{StaticResource SmalllMarginTextBlock}" />
</StackPanel>
<TextBlock Text="Description:" Style="{StaticResource SmalllMarginTextBlock}" Grid.Row="3" Grid.Column="0" />
<TextBox Text="" HorizontalAlignment="Left" Grid.Column="1" Grid.Row="3" Style="{StaticResource SmallMargin}" Width="350" />
<dx:DXTabControl Grid.Row="4" Grid.ColumnSpan="2">
<dx:DXTabItem x:Name="tabAttributes" Header="License Attributes" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="Activation Mode:" Style="{StaticResource TabMargin}" />
<dx:DropDownButton Grid.Row="0" Grid.Column="1" Width="100" HorizontalAlignment="Left" Style="{StaticResource TabMargin}" ButtonKind="Repeat" />
<TextBlock Text="Grace Period:" Style="{StaticResource TabMargin}" Grid.Row="1"/>
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
<dxe:SpinEdit Width="80" Style="{StaticResource TabMargin}" MinValue="0" MaxValue="100" IsReadOnly="True" Value="10" Mask="n0"/>
<TextBlock Text="Days" Style="{StaticResource TabMargin}" />
</StackPanel>
<dxe:CheckEdit Grid.Row="2" Content="Expiration Date" IsChecked="False" />
<dxe:DateNavigator Grid.Row="2" Grid.Column="1" Width="185" HorizontalAlignment="Left" Style="{StaticResource TabMargin}" />
<TextBlock Text="Max Computers:" Grid.Row="3" Style="{StaticResource TabMargin}"/>
<dxe:SpinEdit Grid.Row="4" Grid.Column="1" HorizontalAlignment="Left" Width="80" Margin="2.5,2.5,2.5,1" MinValue="0" MaxValue="100" IsReadOnly="True" Value="10" Mask="n0"/>
</Grid>
</dx:DXTabItem>
<dx:DXTabItem Header="Product Features" x:Name="tabProductFeatures" Visibility="Visible">
<StackPanel Orientation="Vertical" >
<dxe:CheckEdit Content="Standard" Name="chkStandard" IsReadOnly="True" Style="{StaticResource ckkStyle}" />
<dxe:CheckEdit Content="Admin Mode" Name="chkAdminMode" IsReadOnly="True" Style="{StaticResource ckkStyle}" />
<dxe:CheckEdit Content="Batch Mode" Name="chkBatchMode" IsReadOnly="True" Style="{StaticResource ckkStyle}" />
<dxe:CheckEdit Content="Custom Data Series" Name="chkCustomDataSeries" IsReadOnly="True" Style="{StaticResource ckkStyle}" />
<dxe:CheckEdit Content="Local DataBase" Name="LocalDataBase" IsReadOnly="True" IsChecked="True" Style="{StaticResource ckkStyle}"/>
<dxe:CheckEdit Content="Cloud Data Base" Name="CloudDataBase" Style="{StaticResource ckkStyle}" />
</StackPanel>
</dx:DXTabItem>
<dx:DXTabItem Name="tabComputers" Header="Computers">
<dxg:GridControl Name="grdComputers">
</dxg:GridControl>
</dx:DXTabItem>
<dx:DXTabItem Name="tabMain_Schedule" Header="Maint. Schedule">
<dxg:GridControl>
</dxg:GridControl>
</dx:DXTabItem>
<dx:DXTabItem x:Name="tabFeaturePB" Header="Product Features">
<StackPanel Orientation="Vertical">
<dxe:CheckEdit Content="pb" Name="chkpb" IsReadOnly="True" Style="{StaticResource ckkStyle}" />
<dxe:CheckEdit Content="pb2" Name="chkpb2" IsReadOnly="True" Style="{StaticResource ckkStyle}" />
</StackPanel>
</dx:DXTabItem>
</dx:DXTabControl>
</Grid>
The DataContext class of the mainwindows is this
public class CustomerLicenses
{
private Customer _Customer;
private LicenseList _Licenses;
private License _SelectedLicense;
//private Guid _SelectedSerial;
//public delegate void SelectLicenseEventArg(String SerialNum);
//public event SelectLicenseEventArg SelectLicense;
public CustomerLicenses(Customer Customer)
{
_Customer = Customer;
}
public CustomerLicenses(Customer customer, LicenseList licenses)
{
_Customer = customer;
_Licenses = licenses;
}
public CustomerLicenses()
{
_Customer = new Customer();
_Licenses = new LicenseList();
}
[DataMember]
public Customer Customer
{
get { return _Customer; }
set
{
if (_Customer != value)
{
this._Customer = value;
this.NotifyPropertyChanged("Customer");
}
}
}
[DataMember]
public LicenseList Licenses
{
get { return _Licenses;}
set
{
if (_Licenses != value)
{
this._Licenses = value;
this.NotifyPropertyChanged("Licenses");
}
}
}
private DataTable GetLicensesTable()
{
var dt = new DataTable();
dt.Columns.AddRange(new DataColumn []{
new DataColumn("SerialNumber",typeof(string)),
new DataColumn("Product",typeof(string)),
new DataColumn("Status",typeof(string)),
new DataColumn("ActivationMode",typeof(string)),
new DataColumn("MaxComputers", typeof(int)),
new DataColumn("NumActive",typeof(int)),
new DataColumn("Description",typeof(string)),
new DataColumn("License",typeof(object))
});
_Licenses.ForEach((x) => {
var rw = dt.NewRow();
rw["SerialNumber"] = x.SerialNumber;
rw["Product"] = x.Product.Name;
rw["Status"] = x.Status;
rw["ActivationMode"] = Enum.GetName(typeof(ActivationModeEnum), x.ActivationMode); //x.ActivationMode;
rw["MaxComputers"] = x.MaxComputers;
rw["NumActive"] = Activated(x.Product.ProductId);
rw["Description"] = x.Description;
rw["License"] = x;
dt.Rows.Add(rw);
});
return dt;
}
public DataTable LicensesTable{
get { return GetLicensesTable(); }
}
[DataMember]
public License SelectedLicense {
get { return _SelectedLicense;}
set {
this.NotifyPropertyChanged("SelectedLicense");
_SelectedLicense = value;
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propName));
}
}
In this part im populating the textblock with the serial, and is ok it shows when i start the app `cause takes the first license but if i select another license the text does not change.
TextBlock Text="{Binding Path=DataContext.SelectedLicense.SerialNumber, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType=Window}}" x:Name="txtSerialNum" Grid.Column="1" Grid.Row="1" Style="{StaticResource ResourceKey=SmalllMarginTextBlock}"
This is how i assaing the value when the grid chanege selection
private void GridRowSelected (object sender, SelectedItemChangedEventArgs e)
{
try
{
var Record = (DataRowView)grdLicenses.grdLicences.SelectedItem;
var SelectedLicense = (License)Record["License"];
_CustomerLicense.SelectedLicense = SelectedLicense;
//Customer_Detail.DataContext = SelectedCustomer;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
How can i update the child when the item is selected in the grid.
Regards
sTrenat, as you said i checked the class and i was wrong implementing the propertyfotify
i changed to this
[DataContract]
public class CustomerLicenses: System.ComponentModel.INotifyPropertyChanged
{
public void NotifyPropertyChanged(string propName)
{
System.ComponentModel.PropertyChangedEventHandler handler = PropertyChanged;
if (this.PropertyChanged != null)
this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propName));
}
}

WPF MVVM ListBox does not display last record

I find the problem I have very strange.
I have a WPF application using MVVM pattern.
I retrieve data from my database using Linq-to-SQL and display the Description field data in a ListBox using binding.
It works, but not completely. For some reason the last record's does not display. I have verified it is fetched from the database. It cannot be selected; its not there at all.
The only way to get the record to appear is by setting focus to the ListBox and either scrolling the mouse scroller or actually moving down using the keyboard to past the last record (which is supposed to be the second last record). Once you do that, the record appears.
Another way to get the record to show up is update any of the records in the ListBox. I have a TextBox bound in two-way mode to the SelectedItem of the ListBox, So when I select an item, change the text in the TextBox and click the Update button, it calls the Command to do the database update, which works fine, but then also the missing record of the last record shows up.
Is there a rendering problem with ListBox and ListView, because I have tried both? Why does it seem like the ListBox needs to be "redrawn" before the last items appears?
CategoryModel.cs
public class CategoryModel
{
public int CategoryID { get; set; }
public string Description { get; set; }
public List<CategoryModel> categories = new List<CategoryModel>();
readonly SalesLinkerDataContext _dbContext = new SalesLinkerDataContext();
public void GetCategories()
{
categories.Clear();
var result = _dbContext.tblSalesCategories.ToList();
foreach (var item in result)
{
categories.Add(new CategoryModel
{
CategoryID = item.CategoryID,
Description = item.Description.Trim()
});
}
}
internal void Update(CategoryModel cm)
{
try
{
var category = (from a in _dbContext.tblSalesCategories
where a.CategoryID == cm.CategoryID
select a).FirstOrDefault();
if (category != null)
{
category.Description = cm.Description;
_dbContext.SubmitChanges();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
CategoriesViewModel.cs
public class CategoriesViewModel : ViewModelBase, IPageViewModel
{
public CategoryModel Categories = new CategoryModel();
private DelegateCommand _getCategoriesCommand;
private DelegateCommand _updateCategoryCommand;
/// <summary>
/// Describes the name that will be used for the menu option
/// </summary>
public string Name
{
get { return "Manage Categories"; }
}
public string Description
{
get { return Categories.Description; }
set
{
Categories.Description = value;
OnPropertyChanged("Description");
}
}
public List<CategoryModel> ReceivedCategories
{
get { return Categories.categories; }
set
{
Categories.categories = value;
OnPropertyChanged("ReceivedCategories");
}
}
public ICommand GetCategoriesCommand
{
get
{
if (_getCategoriesCommand == null)
{
_getCategoriesCommand = new DelegateCommand(GetCategories, CanGetCategories);
}
return _getCategoriesCommand;
}
}
private bool CanGetCategories()
{
return true;
}
private void GetCategories()
{
Categories.GetCategories();
ReceivedCategories = Categories.categories;
}
public ICommand UpdateCategoryCommand
{
get
{
if (_updateCategoryCommand == null)
{
_updateCategoryCommand = new DelegateCommand(UpdateCategory, CanUpdateCategory);
}
return _updateCategoryCommand;
}
}
private bool CanUpdateCategory()
{
return true;
}
private void UpdateCategory()
{
Categories.Update(Categories);
}
}
CategoriesView.xaml
<UserControl x:Class="SalesLinker.CategoriesView"
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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="600" Background="White" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding GetCategoriesCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="45"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Margin="20,0,0,0" FontSize="20" HorizontalAlignment="Center" Content="Categories"/>
<ListView x:Name="LstCategories" ItemsSource="{Binding ReceivedCategories, Mode=TwoWay}" Grid.Column="0" Grid.Row="1"
VerticalAlignment="Stretch"
Background="LightGray"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionChanged="LstCategories_OnSelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch" >
<TextBlock Text="{Binding Description }"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Command="{Binding AddCategoryCommand}" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" Height="50" Width="50" Margin="0,20,0,0" Background="Transparent" BorderThickness="0" BorderBrush="Transparent" >
<Image Source="/Images/Plus.png"/>
</Button>
<Button Command="{Binding RemoveCategoryCommand}" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" Height="50" Width="50" Margin="0,75,0,0" Background="Transparent" BorderThickness="0">
<Image Source="/Images/Minus.png"/>
</Button>
<Grid Grid.Row="1" Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0" Content="Description:"/>
<TextBox DataContext="CategoryModel" Grid.Row="0" Grid.Column="1" Width="250" Height="Auto" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0"
Text="{Binding SelectedItem.Description, ElementName=LstCategories}"/>
<Button Command="{Binding UpdateCategoryCommand}"
Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Margin="10,0,0,0" Height="20" Width="120" Content="Update Description"/>
</Grid>
</Grid>
I am very new to MVVM so hopefully I am just not seeing something simple.
For some reason the last record's does not display. I have verified it is fetched from the database.
If your fetch all data from database, then it can be concluded that why you cannot see your last item is as you use using not correct layout. I mean static layout.
I suggest you to use dynamic layout, not static. I mean it is bad:
<Grid.RowDefinitions>
<RowDefinition Height="45"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
The following code is better and it affords you to see all items to be seen and to be resized accoriding the display and Width and Height of your Window or UserControl:
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
Let me show the full example:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Margin="20,0,0,0" FontSize="20" HorizontalAlignment="Center" Content="Categories"/>
<ListView x:Name="LstCategories" ItemsSource="{Binding ReceivedCategories, Mode=TwoWay}" Grid.Column="0" Grid.Row="1"
VerticalAlignment="Stretch"
Background="LightGray"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch" >
<TextBlock Text="{Binding Description }"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Command="{Binding AddCategoryCommand}" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" Height="50" Width="50" Margin="0,20,0,0" Background="Transparent" BorderThickness="0" BorderBrush="Transparent" >
<Image Source="/Images/Plus.png"/>
</Button>
<Button Command="{Binding RemoveCategoryCommand}" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" Height="50" Width="50" Margin="0,75,0,0" Background="Transparent" BorderThickness="0">
<Image Source="/Images/Minus.png"/>
</Button>
<Grid Grid.Row="1" Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1.5*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Label VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0" Content="Description:"/>
<TextBox DataContext="CategoryModel" Grid.Row="0" Grid.Column="1" Height="Auto" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0"
Text="{Binding SelectedItem.Description, ElementName=LstCategories}"/>
<Button Command="{Binding UpdateCategoryCommand}"
Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Content="Update Description"/>
</Grid>
Update:
In order to dispel any doubts, I've made a test to show that all items are shown:
I've made some test model class:
public class FooClass
{
public string Description { get; set; }
}
And I've populated your ListView in a loop:
public MainWindow()
{
InitializeComponent();
PopulateCollection();
}
private void PopulateCollection()
{
List<FooClass> fooColl = new List<FooClass>();
for (int i = 0; i <= 1000; i++)
{
fooColl.Add(new FooClass() { Description=i.ToString()});
}
LstCategories.ItemsSource = fooColl;
}
XAML:
<ListView x:Name="LstCategories" Grid.Column="0" Grid.Row="1"
VerticalAlignment="Stretch"
Background="LightGray"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch" >
<TextBlock Text="{Binding Description }"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The result is:

Silverlight, XAML, DataGrid does not autosize, no auto scrollbars

Can anyone tell me why the datagrid in this example gets cut off when it grows past the bounds of the Grid.Row which contains it? Here is the xaml and code-behind which you can use in a VS 2010 'Silverlight Application' template. Thanks in advance.
<UserControl
x:Class="SilverlightApplication3.MainPage"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
mc:Ignorable="d" >
<Grid>
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- header -->
<Border Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="40" >
</Border>
<!-- employee category selection -->
<Grid Grid.Row="1" Margin="10">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Category:" Margin="0,0,10,0" VerticalAlignment="Center" />
<ComboBox ItemsSource="{Binding EmployeeTypes}" SelectedItem="{Binding EmployeeType, Mode=TwoWay}" MinWidth="100" />
</StackPanel>
<Border BorderBrush="Black" BorderThickness="10" Height="2" Margin="0,10,0,0" ></Border>
</StackPanel>
</Grid>
<!-- content -->
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- daily employee grid -->
<Grid Grid.Row="0" Visibility="Visible" Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="Category Type:" />
<ComboBox ItemsSource="{Binding Categories}"
SelectedItem="{Binding Category, Mode=TwoWay}"
DisplayMemberPath="Name" HorizontalAlignment="Left" Width="250">
</ComboBox>
<TextBlock Text="Category Types:" Margin="0,10,0,0" />
<sdk:DataGrid x:Name="dataGrid" AutoGenerateColumns="True"
HorizontalAlignment="Left" VerticalAlignment="Stretch" MinWidth="250" VerticalScrollBarVisibility="Visible" >
<sdk:DataGrid.ColumnHeaderStyle>
<Style TargetType="sdk:DataGridColumnHeader">
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</sdk:DataGrid.ColumnHeaderStyle>
</sdk:DataGrid>
</StackPanel>
</Grid>
</Grid>
<!-- buttons -->
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0" >
<Button Command="{Binding SaveCommand}"
Width="80" HorizontalContentAlignment="Center" Margin="0,0,2,0">
<StackPanel Orientation="Horizontal">
<Image Source="../Images/Approve24x24.png" Height="24" Width="24"/>
<TextBlock Text="Save" VerticalAlignment="Center" Margin="2"/>
</StackPanel>
</Button>
<Button Command="{Binding CancelCommand}"
Width="80" HorizontalContentAlignment="Center">
<StackPanel Orientation="Horizontal">
<Image Source="../Images/Delete24x24.png" Height="24" Width="24"/>
<TextBlock Text="Cancel" VerticalAlignment="Center" Margin="2"/>
</StackPanel>
</Button>
</StackPanel>
</Grid>
</Border>
</Grid>
and the code-behind:
using System.Collections.Generic;
using System.Windows.Controls;
namespace SilverlightApplication3
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
List<string> testItems = new List<string>();
for (int i = 0; i < 50; i++)
{
testItems.Add(string.Format("Item Number {0}", i.ToString()));
}
this.dataGrid.ItemsSource = testItems;
}
}
}
You used the StackPanel to display some elements and datagrid. So here datagrid is not constrained to any height, moreover the the parent grid of stackpanel's height is Auto. So there is no where you are making grid to occupy fixed size.
I modified your code with in a grid.
<!-- content -->
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- daily employee grid -->
<Grid Grid.Row="0" Visibility="Visible" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="28" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="Category Type:" />
<ComboBox ItemsSource="{Binding Categories}"
SelectedItem="{Binding Category, Mode=TwoWay}"
DisplayMemberPath="Name" HorizontalAlignment="Left" Width="250">
</ComboBox>
</StackPanel>
<TextBlock Text="Category Types:" Margin="0,10,0,0" Grid.Row="1" />
<sdk:DataGrid x:Name="dataGrid" AutoGenerateColumns="True" Grid.Row="2" ScrollViewer.VerticalScrollBarVisibility="Visible" Margin="10"
HorizontalAlignment="Left" VerticalAlignment="Top" MinWidth="250" VerticalScrollBarVisibility="Visible" >
<sdk:DataGrid.ColumnHeaderStyle>
<Style TargetType="sdk:DataGridColumnHeader">
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</sdk:DataGrid.ColumnHeaderStyle>
</sdk:DataGrid>
</Grid>
</Grid>
This should give you the expected result.

MVVM + UserControl + UserControl + DependencyProperty

I have a user control which displays addresses housed inside of another page that is bound to a viewmodel. The viewmodel has a primitive User which has a collection of Address objects. The User control will reside on several pages so I would like to be able to bind it to the address list via a dependency property. While my current solution is working, something about it just doesn't feel right and I thought I'd ask for a second opinion. I have chopped out a lot of code for brevity's sake.
Basically the page binds to the dependency property in the usercontrols code behind which then updates the usercontrol's datagrid by setting it's itemsource. This seems to me to break the basic tenants of MVVM.
AddressListView control:
<UserControl x:Class="Insight.Controls.AddressListView"
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:tk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
xmlns:command="clr-namespace:PrismFramework.Implementors.Commanding;assembly=PrismFramework"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="840">
<UserControl.Resources>
<command:ObservableCommand x:Name="EditAddressCommand" Value="{Binding EditAddressCmd}"/>
<command:ObservableCommand x:Name="DeleteAddressCommand" Value="{Binding DeleteAddressCmd}"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<sdk:DataGrid Name="dgAddresses"
Height="Auto"
Width="Auto"
AutoGenerateColumns="False"
HeadersVisibility="None" >
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn x:Name="dgcAddresses"
Width="*" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border x:Name="bdrAddress"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="Auto"
BorderBrush="Silver"
BorderThickness="1"
Padding="0"
Margin="1,1,1,1">
<Grid x:Name="grdAddressItem"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="17" MinHeight="17"/>
<RowDefinition Height="17" MinHeight="17"/>
<RowDefinition Height="17" MinHeight="17"/>
<RowDefinition Height="17" MinHeight="17"/>
<RowDefinition Height="17" MinHeight="17"/>
<RowDefinition Height="17" MinHeight="17"/>
<RowDefinition Height="17" MinHeight="17"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="55" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Padding="0,0,5,0" Text="Type:" TextAlignment="Right" />
<TextBlock Grid.Column="1" Padding="0" Text="{Binding Path=AType}" Grid.ColumnSpan="2" />
<TextBlock Grid.Row ="1" Grid.Column="0" Padding="0,0,5,0" Text="Address 1:" TextAlignment="Right" />
<!-- List Of Similar Fields ->
<Grid x:Name="grdAddressEditOptions"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="Auto"
Grid.Column="3"
Grid.RowSpan="7" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button x:Name="btnEdit"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="Auto"
Grid.Row="0"
Padding="4,5,4,8"
Margin="0,8,10,0"
Command="{Binding Value, Source={StaticResource EditAddressCommand}}"
CommandParameter="{Binding}" >
<Button.Content>
<Image x:Name="btnEditIcon"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="Auto"
Width="Auto"
Source="/Insight.ModuleUser;component/Images/edit.png"
Visibility="Visible" />
</Button.Content>
</Button>
<Button x:Name="btnDelete"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="Auto"
Grid.Row="2"
Padding="4,5,4,8"
Margin="0,0,10,5"
Command="{Binding Value, Source={StaticResource DeleteAddressCommand}}"
CommandParameter="{Binding}" >
<Button.Content>
<Image x:Name="btnDeleteIcon"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="Auto"
Width="Auto"
Source="/Insight.ModuleUser;component/Images/delete.png"
Visibility="Visible" />
</Button.Content>
</Button>
</Grid>
</Grid>
</Border>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</UserControl>
AddressListView code behind:
Imports System.Collections.ObjectModel
Imports Insight.DataServices.Primitives
Partial Public Class AddressListView
Inherits UserControl
Public ReadOnly AddressesProperty As DependencyProperty = DependencyProperty.Register("Addresses", GetType(ObservableCollection(Of Address)), GetType(AddressListView), New PropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnAddressesChanged)))
Public Sub New()
InitializeComponent()
End Sub
Public Property Addresses As ObservableCollection(Of Address)
Get
Return DirectCast(GetValue(AddressesProperty), ObservableCollection(Of Address))
End Get
Set(value As ObservableCollection(Of Address))
SetValue(AddressesProperty, value)
End Set
End Property
Public Sub OnAddressesChanged()
Me.dgAddresses.ItemsSource = Addresses
End Sub
End Class
Base page:
<UserControl x:Class="Insight.ModuleUser.Views.EditUserView"
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Interactivity.InteractionRequest;assembly=Microsoft.Practices.Prism.Interactivity"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cm="clr-namespace:System.ComponentModel;assembly=System.Windows"
xmlns:data="clr-namespace:System.Windows.Data;assembly=System.Windows"
xmlns:vm="clr-namespace:Insight.ModuleUser.ViewModels"
xmlns:command="clr-namespace:PrismFramework.Implementors.Commanding;assembly=PrismFramework"
xmlns:controls="clr-namespace:Insight.Controls;assembly=Insight.Controls"
xmlns:modalDialogs="clr-namespace:Insight.Controls.ModalDialogViews;assembly=Insight.Controls"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="1144"
d:DataContext="{d:DesignData /Insight.ModuleUser;component/SampleData/EditUserViewModelSampleData.xaml}">
<UserControl.Resources>
<command:ObservableCommand x:Name="OpenProjectCommand" Value="{Binding OpenProjectCmd}"/>
<command:ObservableCommand x:Name="OpenPaymentCommand" Value="{Binding OpenPaymentCmd}"/>
<command:ObservableCommand x:Name="OpenInvoiceCommand" Value="{Binding OpenInvoiceCmd}"/>
<command:ObservableCommand x:Name="OpenPaymentItemCommand" Value="{Binding OpenPaymentItemCmd}"/>
<command:ObservableCommand x:Name="EditPhoneCommand" Value="{Binding EditPhoneNumberCmd}"/>
<command:ObservableCommand x:Name="DeletePhoneCommand" Value="{Binding DeletePhoneNumberCmd}"/>
<command:ObservableCommand x:Name="EditEmailAddressCommand" Value="{Binding EditEmailAddressCmd}"/>
<command:ObservableCommand x:Name="DeleteEmailAddressCommand" Value="{Binding DeleteEmailAddressCmd}"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" >
<controls:AddressListView x:Name="ctrlAddressListView"
Addresses="{Binding User.Addresses}" />
</Grid>
</UserControl>
This seems a perfectly reasonable approach. However, you could use binding in your user control view, rather than setting the items source in code.
To do this you need to set the DataContext of the user control to be your user control type. This could be done either in the code behind for the user control (setting this.DataContext = this), or through element binding in XAML:
<UserControl
...
x:Name="MyName"
DataContext="{Binding ElementName=MyName}"
However, my approach would be not to use a user control at all, as all you're really talking about is view composition and reusing a particular section of the view between other views.
View composition is extremely straightforward with an MVVM framework such as Caliburn.Micro. In this case you would have an AddressViewModel and AddressView, and use a ContentControl to inject the AddressView into the base view:
<ContentControl x:Name="AddressViewModel" />

Resources