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" />
Related
I am trying to create a container-like component. It uses the MaterialDesign Card as a container, places a title in it and allows space for Content.
<ContentControl
x:Class="Client.Components.AisCard"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<materialDesign:Card
Margin="0,0,20,0"
Padding="20,20,20,30">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Text="Opmerkingen"
Style="{StaticResource MaterialDesignHeadline5TextBlock}"
FontWeight="Medium"
Margin="0,0,0,10" />
<ContentPresenter Grid.Row="1" />
</Grid>
</materialDesign:Card>
</ContentControl>
Then, I call the Component in a view and attempt to fill its Content:
<Components:AisCard
Grid.Column="0"
Grid.Row="0">
<TextBlock Text="Hello World" />
</Components:AisCard>
The result looks like this:
I expected it to look like this:
Maybe I have misunderstood the way that a ContentPresenter works. Maybe using a Component inside of a Component is not the way to go. Could anyone offer some form of assistance in the matter?
The TextBlock replaces the Card, because both just set the Content property. You would have to declare the Card as part of a ControlTemplate:
<ContentControl
x:Class="Client.Components.AisCard"
...>
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<materialDesign:Card
Margin="0,0,20,0"
Padding="20,20,20,30">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Text="Opmerkingen"
Style="{StaticResource MaterialDesignHeadline5TextBlock}"
FontWeight="Medium"
Margin="0,0,0,10" />
<ContentPresenter Grid.Row="1" />
</Grid>
</materialDesign:Card>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
I have 3 user controls
One is the parent that holds a GridViewUserControl and a ExportUserControl
The GridViewUserControl and ExportUserControl have their own viewmodels.
When I click the ExportButton in the ExportUserControl I need to pass the gridview to a command in the ExportUserControl. Everything I try is always passing null.
How would I do something like this? ( This is giving the error "binding.elementname cannot be set while using binding.relativesource"
<telerik:RadButton Content="Export"
Command="{Binding ExportCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=view:GridViewUserControl}, ElementName=GridViewData}"
Margin="0,10,0,0" />
EDIT: Parent Control looks like this
<UserControl x:Class="Sample.Sample1.View.ParentUserControl"
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:view="clr-namespace:GroundStation.Configuration.Viewer.View"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="150"/>
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<view:ExportUserControl Margin="5"
Grid.Column="0"
Grid.Row="2"
Grid.RowSpan="2"
MinWidth="150"
/>
<GridSplitter Grid.Column="1"
Width="5"
Grid.Row="1"
Grid.RowSpan="3"
HorizontalAlignment="Stretch" />
<view:GridViewUserControl
Margin="5"
Grid.Column="2"
Grid.Row="1"
Grid.RowSpan="3"/>
</Grid>
</UserControl>
I have a small but annoying problem with my ContextMenu in a WPF application.
I use a DataTemplate for my List of ViewModel-objects to create the visual elements. In the DataTemplate I simply set my UserControl like this:
<!-- Define a data-template for the 'RoomViewModel' class. This generates the UI for each node. -->
<DataTemplate DataType="{x:Type model:RoomViewModel}">
<network:RoomView network:ConstraintView.ArgumentChanged="ConstraintView_ArgumentChanged"></network:RoomView>
</DataTemplate>
I want the RoomView to have a ContextMenu where a RelayCommand should be executed if the user clicks on the MenuItem. My UserControl for the RoomView looks like this at the moment:
<UserControl x:Name="userControl" x:Class="NetworkUI.RoomView"
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:network="clr-namespace:NetworkUI"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" DataContextChanged="userControl_DataContextChanged">
<UserControl.Resources>
<!-- UI commands -->
<RoutedCommand x:Key="Commands.NewConstraintCmd"></RoutedCommand>
</UserControl.Resources>
<UserControl.CommandBindings>
<CommandBinding x:Name="newConst" Command="{StaticResource Commands.NewConstraintCmd}" Executed="NewConstraint_Executed"></CommandBinding>
</UserControl.CommandBindings>
<Grid Width="Auto" Height="Auto" MinWidth="50" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Width="Auto" Height="20" MinWidth="50" >
<Rectangle Stroke="Black" Fill="White" RadiusX="4" RadiusY="4" SnapsToDevicePixels="True" ></Rectangle>
<Grid Margin="-4" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" MinWidth="10" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<network:EditableTextBlock Grid.Column="1" Grid.Row="1" x:Name="nameTextBox" Text="{Binding Name, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="{x:Null}" />
<network:ConnectorItem Grid.Row="1" Grid.Column="0" DataContext="{Binding Connectors[0]}" />
<network:ConnectorItem Grid.Row="1" Grid.Column="2" DataContext="{Binding Connectors[1]}" />
</Grid>
</Grid>
<StackPanel Grid.Row="1" x:Name="roomProperties" Width="Auto" HorizontalAlignment="Stretch" >
<ItemsControl ItemsSource="{Binding PropertyGroups}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<network:ConstraintCollectionView></network:ConstraintCollectionView>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
<UserControl.ContextMenu>
<ContextMenu x:Name="contextMenu">
<MenuItem Header="new Constraint" Command="{StaticResource Commands.NewConstraintCmd}"></MenuItem>
</ContextMenu>
</UserControl.ContextMenu>
</UserControl>
I am not really sure if my UserControl code is ok. In my CodeBehind file I define a
public ICommand NewConstraintCmd;
-Command that should be executed when the user clicks the Item. My Executed handler is simple and looks like this:
private void NewConstraint_Executed(object sender, ExecutedRoutedEventArgs e) {
ViewModel.AddConstraint();
}
The ViewModel is indeed a RoomViewModel and the NewConstraintCmd is set in the DataContextChanged - event (not displayed here).
My simple question is, why is my ContextMenu-Item always disabled? I mean the RelayCommand.CanExecute is never checked, is this the problem maybe?
I didn't find any solution for my problem yet.
Thank you for any help!
Thank you Rohit Vats! I changed my ICommand definition to this:
public static readonly ICommand NewConstraint = new RelayCommand((rvm) => AddConstraint(rvm));
Since this is a static method I needed the parameter (the DataContext of my RoomView).
My Method is defined like this now:
private static void AddConstraint(object rvm) {
if (rvm is RoomViewModel)
(rvm as RoomViewModel).AddConstraint();
}
So first the parameter is checked and if it is ok (a RoomViewModel object) I call the actual function on the object.
I have no idea why it works now, really :/.
My XAML code for the MenuItem now looks like this:
<MenuItem Header="new Constraint" Command="network:RoomView.NewConstraint" CommandParameter="{Binding}"></MenuItem>
As mentioned before I need the CommandParameter to call a function on it. Since the needed Object is my DataContext I just use the {Binding} to pass the object.
This really works fine now, I hope it will work with InputBindings as well in the future :)!
Thank you again for the help!
I have a user control that has its datacontext set to a view model called EmployeeList_VM. I then have a ContentControl within that user-control that has its datacontect set to a public property (EmployeeSelection) of the view model. The ContentControl's datacontext is the same as the selected item binding of a listbox within the same user control.
I want to have a combobox (of an observblecollection called EmployeeStatus) within the ContentControl bind its selecteditem to a property of the EmployeeSelection datacontext of the ContentControl. I want the itemssource of the combobox to bind to a public property EmployeeStatus of the "parent" viewmodel EmployeeList_VM.
I can get a list of the employees status to appear wihtin the combobox. I can not get it to bind to the idStatus property of the EmployeeSelection.
Here is What I have so far (some code removed for readability):
<UserControl x:Class="FTC.View.EmployeeListView"
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:FTC_Application"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="http://www.galasoft.ch/mvvmlight"
mc:Ignorable="d"
DataContext="{Binding EmployeeList_VM, Source={StaticResource Locator}}"
d:DesignHeight="900" d:DesignWidth="1000">
<Expander x:Name="DetailExpander" Grid.Column="2" Header="employee detail" Style="{DynamicResource ExpanderStyle_FTC}" IsExpanded="True" Padding="8,0,0,10" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" HorizontalAlignment="Left" >
<Button Content="" Style="{DynamicResource ButtonSave}" Command="{Binding SaveCommand}" ToolTip="Save Changes" Margin="0,0,10,10"/>
<Button Content="" Style="{DynamicResource ButtonUndo}" Command="{Binding UndoCommand}" ToolTip="Undo Changes" Margin="0,0,10,10"/>
</StackPanel>
<ScrollViewer Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ContentControl DataContext="{Binding Path=EmployeeSelection, Mode=TwoWay}" >
<!-- FTC SETTINGS GRID CONTENT-->
<Grid Grid.ColumnSpan="6" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="SettingsHeading" Text="FTC Settings" Style="{StaticResource FTC_DetailHeading}" Grid.ColumnSpan="5"/>
<TextBlock Text="Status" Style="{StaticResource FTC_DetailLabelSub}" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1"/>
<ComboBox Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2"
Margin="5,5,16,5" Height="37"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.EmployeeStatus}"
SelectedItem="{Binding idStatus, Mode=TwoWay}"
SelectedValuePath="idStatus"
DisplayMemberPath="chrCode" FontSize="18"/>
</Grid>
</ContentControl>
</ScrollViewer>
</Grid>
</Expander>
</UserControl>
I even tried the following change (I named the ContentControl DetailControl) for the selected item of the combobox:
SelectedItem="{Binding ElementName=DetailControl, Path=DataContext.idStatus}"
Can someone please help me get the selected item binding hooked up properly. The combobox displays all the right items, but they do not bind to the EmployeeSelection.idStatus.
Thanks in advance.
so here is what worked for me, hope it can help someone else
<ComboBox Name="cbStatus" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2"
Style="{StaticResource FTC_DetailComboBox}"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.EmployeeStatus}"
SelectedItem="{Binding ElementName=DetailControl, Path=DataContext.employee_status}"
SelectedValuePath="idStatus"
SelectedValue="{Binding idStatus, Mode=TwoWay, ValidatesOnDataErrors=True}"
DisplayMemberPath="chrCode"/>
Just trying to get my head round WPF. I have a usercontrol which I'm using as the template for items in a listbox, however no matter what I try the usercontrol's width is always shrinking to the minimum size but I want it to fill the available width. I've found a similar query on here but it was relating just to a usercontrol not within a listbox and the solution proposed doesn't apply here.
My UserControl is defined as :
<UserControl x:Class="uReportItem"
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"
d:DesignHeight="60" d:DesignWidth="300">
<Grid >
<Border CornerRadius="3,3,3,3" BorderBrush="#0074BA" BorderThickness="1" Background="#00D6F9" Margin="0">
<DockPanel Margin="3,3,3,3">
<Grid Height="Auto">
<!-- Grid Definition-->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- Content -->
<!-- Top Row-->
<Button Grid.RowSpan="2">Delete</Button>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<Label x:Name="Heading" Content="{Binding Heading}" FontSize="14" FontWeight="bold"></Label>
<Label x:Name="Subheading" Content="{Binding SubHeading}" FontSize="14"></Label>
</StackPanel>
<Button Grid.Column="2">Blah</Button>
<!-- Second Row-->
<Label Grid.Row="1" Grid.Column="1" x:Name="Comments">Comments</Label>
<Button Grid.Column="2">Blah</Button>
</Grid>
</DockPanel>
</Border>
</Grid>
And the implementation on the window is :
<Window x:Class="vReport"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RecorderUI"
Title="vReport" Height="300" Width="300" Background="#00BCF0">
<Window.Resources>
<DataTemplate x:Key="Record" DataType="ListItem">
<Grid>
<local:uReportItem></local:uReportItem>
</Grid>
</DataTemplate>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<local:uReport Margin="5" Grid.Row="0"></local:uReport>
<Border Grid.Row="1" BorderBrush="#0074BA" CornerRadius="3">
<ListBox Margin="5" Background="#00D6F9" BorderBrush="#0074BA" x:Name="ListRecords" ItemsSource="{Binding Items}" ItemTemplate ="{StaticResource Record}"></ListBox>
</Border>
<TextBlock Grid.Row="2" x:Name="SelectedItem" Text="{Binding Path=SelectedItem.Heading, Mode=TwoWay}"></TextBlock>
</Grid>
Any ideas?
Try setting HorizontalContentAlignment to Stretch on the ListBox:
<ListBox Margin="5" Background="#00D6F9" BorderBrush="#0074BA" x:Name="ListRecords" ItemsSource="{Binding Items}" ItemTemplate ="{StaticResource Record}" HorizontalContentAlignment="Stretch"></ListBox>