XAML - Bind combobox in DataTemplate to a collection? - c#

Firstly, thank you for taking the time out to read this post. All contributions are very much appreciated.
I'm having difficulty understanding how I can bind a ComboBox ItemsSource within a DataTemplate to an ObservableCollection.
Here's my code thus far:
DataTemplate Template (notice the combo's at the bottom of the template):
<DataTemplate x:Key="ListBoxCustomTemplate">
<Grid Margin="4" HorizontalAlignment="Stretch" x:Name="lstBoxItemRoomGrid" >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontWeight="Bold" Text="{Binding TemplateGroupName}" />
<Image x:Name="imgDeleteListBoxItem" Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Source="/Icons/Print-Groups-Config/delete-32.png" Height="25" Cursor="Hand"
ToolTip="Remove template" VerticalAlignment="Center"
HorizontalAlignment="Right" MouseLeftButtonUp="imgDeleteListBoxItem_MouseLeftButtonUp">
<Image.Style>
<Style>
<Setter Property="Image.Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=lstBoxItemRoomGrid}" Value="True">
<Setter Property="Image.Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Text="{Binding TemplateDescription}" TextWrapping="WrapWithOverflow" />
<!-- Header Template Selection -->
<Label Grid.Row="2" Grid.Column="0" Margin="0,3,0,0" HorizontalAlignment="Left" VerticalAlignment="Bottom" Content="Select Header:" FontWeight="DemiBold" Foreground="DarkGray" />
<telerik:RadComboBox x:Name="radComboHeaderTemplate" Grid.Row="3" Grid.Column="0" Width="120" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"
ClearSelectionButtonVisibility="Visible" SelectedValue="{Binding TemplateHeaderID}" />
<!-- Footer Template Selection -->
<Label Grid.Row="2" Grid.Column="1" Margin="0,3,0,0" HorizontalAlignment="Left" VerticalAlignment="Bottom" Content="Select Footer:" FontWeight="DemiBold" Foreground="DarkGray" />
<telerik:RadComboBox x:Name="radComboFooterTemplate" Grid.Row="3" Grid.Column="1" Width="120" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"
ClearSelectionButtonVisibility="Visible" SelectedValue="{Binding TemplateFooterID}" />
</Grid>
</DataTemplate>
When my Window loads, I download the collection data from my database and store into a local collection. Note that there are two Collections, one for each of the 2 ComboBoxes in my DataTemplate.
//Header Templates
private ObservableCollection<TemplateHeaderFooter> templatesHeader = new ObservableCollection<TemplateHeaderFooter>();
//Footer Templates
private ObservableCollection<TemplateHeaderFooter> templatesFooters = new ObservableCollection<TemplateHeaderFooter>();
//--- Constructors ---
public PrintTemplateGroupsConfigWindow()
{
InitializeComponent();
//Download Data From DB
this.templatesHeader = TemplateHeaderFootersDB.GetAllTemplatesOfType(1);
this.templatesFooters = TemplateHeaderFootersDB.GetAllTemplatesOfType(2);
}
How do I get the collection Data templatesFooters & templatesHeader into the the ItemsSources of their respective ComboBoxes?
The datatemplate is for a ListBox.
<telerik:RadListBox x:Name="lstBoxPrintGroupTemplates" Height="300" Width="280" ItemsSource="{Binding}" IsEnabled="False"
ItemTemplate="{StaticResource ListBoxCustomTemplate}" Style="{StaticResource DraggableListBox}" >
Many thanks. Any help is appreciated.

Define properties wrappers over the variables of your collections and then you can bind them to comboboxes as:
ItemsSource="{Binding TemplatesHeader, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
public ObservableCollection<TemplateHeaderFooter> TemplatesHeader
{
get{return templatesHeader;}
}
Similarly you can do for other property

Related

Not able to get the current active /selected TabITem in DevExpress DxTabControl in WPF

I have a WPF app and I am trying to Automate it using FlaUI. I am facing a problem with the DxTabControl. I have provided Automation IDs to the DxTabControl. I am using DXTabControl.ItemHeaderTemplate to generate TabItems dynamically.
According to DevExpress Team, The DXTabControl.ItemHeaderTemplate doesnt support AutoamtionPeer so a custom implementation has been added to override its default behaviour.
Now, I am able to see the TabControl and the TabItems in the Inspect.exe.
Now , my requirement is to Access the currently selected Tabitem and find the CloseButton using the AutoamtionID mentioned in the XAML below and close it. Pasting below the line again. As there would be multiple TabItems generated, I am unable to get the Currently active/Selected TabItem .
The XAML is below
<dx:DXTabControl AutomationProperties.AutomationId="ViewsParentTabControl"
MaxWidth="4000"
MaxHeight="4000"
Margin="1,0,-1,0"
Focusable="False"
ItemsSource="{Binding OpenViews}"
SelectedIndex="{Binding SelectedTabIndex}"
TabContentCacheMode="CacheTabsOnSelecting">
<dx:DXTabControl.ItemHeaderTemplate>
<DataTemplate DataType="viewModels1:OpenViewDefinitionViewModel">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Name="CreatedViewName"
MaxWidth="100"
Text="{Binding Data.ViewDefinition.Name}"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding DisplayName}" />
<TextBlock Grid.Row="0" Grid.Column="1"><Run Text=" [" /><Run Text="{Binding ItemsCount, FallbackValue=0, Mode=OneWay}" /><Run Text="]" /></TextBlock>
<controls2:ProgressIndicator AutomationProperties.AutomationId="ProgressCurrentView"
Grid.Row="0"
Grid.Column="3"
Width="14"
Margin="4,0,0,0"
VerticalAlignment="Center"
CircleBorder="{StaticResource ListBoxItem.Foreground}"
CircleFill="{StaticResource ListBoxItem.Foreground}"
IndicatorEnabled="{Binding IsDataLoading}" />
<Button AutomationProperties.AutomationId="CloseCurrentViewButton"
Grid.Row="0"
Grid.Column="2"
Width="10"
Height="10"
Margin="10,1,0,0"
Padding="0"
HorizontalAlignment="Right"
BorderThickness="0"
Command="{Binding DataContext.CloseItemCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=dx:DXTabControl}}"
CommandParameter="{Binding}"
Focusable="False"
Style="{StaticResource MwButtonStyle}"
ToolTip="Close">
<Path
Data="F1 M 26.9166,22.1667L 37.9999,33.25L 49.0832,22.1668L 53.8332,26.9168L 42.7499,38L 53.8332,49.0834L 49.0833,53.8334L 37.9999,42.75L 26.9166,53.8334L 22.1666,49.0833L 33.25,38L 22.1667,26.9167L 26.9166,22.1667 Z"
Fill="White"
Stretch="Fill" />
</Button>
</Grid>
</DataTemplate>
</dx:DXTabControl.ItemHeaderTemplate>
<dx:DXTabControl.ItemTemplate>
<DataTemplate DataType="viewModels1:OpenViewDefinitionViewModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:VoyagesGridControl />
<local:VoyageValidationUserControl
Grid.Row="1"
Grid.Column="0"
MinHeight="100"
MaxHeight="300"
Visibility="{Binding Path=IsVoyageValidationShowing, FallbackValue=Collapsed, Converter={StaticResource BooleanToVisibilityConverter}}" />
<local:VoyageHistoryUserControl
Grid.Row="2"
Grid.Column="0"
MinHeight="300"
MaxHeight="300"
Visibility="{Binding Path=IsVoyageHistoryShowing, FallbackValue=Collapsed, Converter={StaticResource BooleanToVisibilityConverter}}" />
<local:VesselHistoryUserControl
Grid.Row="3"
Grid.Column="0"
MinHeight="300"
MaxHeight="300"
Visibility="{Binding Path=IsVesselHistoryShowing, FallbackValue=Collapsed, Converter={StaticResource BooleanToVisibilityConverter}}" />
<local:VoyageEvents
Grid.Row="0"
Grid.RowSpan="3"
Grid.Column="1"
VerticalAlignment="Top"
Visibility="{Binding Path=IsVoyageEventsShowing, FallbackValue=Collapsed, Converter={StaticResource BooleanToVisibilityConverter}}" />
<controls2:ProgressIndicator AutomationProperties.AutomationId="showProgressForLoadingViews"
Grid.Row="0"
Grid.RowSpan="3"
Grid.Column="0"
Width="80"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CircleBorder="{StaticResource ListBox.BorderBrush}"
CircleFill="{StaticResource ListBox.BorderBrush}"
IndicatorEnabled="{Binding IsDataLoading}" />
<!-- Buttons -->
<Grid Grid.Row="4" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock Style="{StaticResource MwTextBlockLabelStyle}" Text="Last Refresh:" />
<TextBlock
Margin="2,0,4,0"
VerticalAlignment="Center"
Text="{Binding LoadDate, StringFormat=G}" />
</StackPanel>
<Button AutomationProperties.AutomationId="AddNewVoyageButton"
Grid.Row="0"
Grid.Column="1"
Padding="0"
Command="{Binding AddVoyagesCommand}"
Focusable="False"
Style="{StaticResource MwButtonStyle}"
ToolTip="Add a new voyage to this View (ALT + A)">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource Add}" />
<Label Style="{StaticResource MwLabelStyle}">_Add</Label>
</StackPanel>
</Button>
<Button AutomationProperties.AutomationId="refreshVoyageButton"
Grid.Row="0"
Grid.Column="2"
Padding="0"
Command="{Binding RefreshVoyagesCommand}"
Focusable="False"
Style="{StaticResource MwButtonStyle}"
ToolTip="Refresh the this View (modified entries are left unchanged)">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource Refresh}" />
<TextBlock Style="{StaticResource MwTextBlockLabelStyle}" Text="Refresh" />
</StackPanel>
</Button>
<Button AutomationProperties.AutomationId="showVoyageHistroyButton"
Grid.Column="4"
Margin="2,2,2,2"
Padding="0"
VerticalAlignment="Center"
Command="{Binding ShowVoyageHistoryCommand}"
Focusable="False"
ToolTip="Show the selected voyage's change history"
Visibility="{Binding Data.ViewDefinition.IsInternalView, Converter={StaticResource MwBoolToVisibilityConverterReverse}}">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource ShowVoyageHistory}" />
<TextBlock
Style="{StaticResource MwTextBlockLabelStyle}"
Text="Hide Voyage History"
Visibility="{Binding IsVoyageHistoryShowing, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBlock
Style="{StaticResource MwTextBlockLabelStyle}"
Text="Show Voyage History"
Visibility="{Binding IsVoyageHistoryShowing, Converter={StaticResource MwBoolToVisibilityConverterReverse}}" />
</StackPanel>
</Button>
<Button AutomationProperties.AutomationId="showVesselHistroyButton"
Grid.Column="5"
Margin="2,2,2,2"
Padding="0"
VerticalAlignment="Center"
Command="{Binding ShowVesselHistoryCommand}"
Focusable="False"
ToolTip="Show the selected vessel's voyage history"
Visibility="{Binding Data.ViewDefinition.IsInternalView, Converter={StaticResource MwBoolToVisibilityConverterReverse}}">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource ShowVesselHistory}" />
<TextBlock
Style="{StaticResource MwTextBlockLabelStyle}"
Text="Hide Vessel History"
Visibility="{Binding IsVesselHistoryShowing, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBlock
Style="{StaticResource MwTextBlockLabelStyle}"
Text="Show Vessel History"
Visibility="{Binding IsVesselHistoryShowing, Converter={StaticResource MwBoolToVisibilityConverterReverse}}" />
</StackPanel>
</Button>
<Button AutomationProperties.AutomationId="showVoyageButton"
Grid.Column="6"
Margin="2,2,2,2"
Padding="0"
VerticalAlignment="Center"
Command="{Binding ShowVesselVisitsCommand}"
Focusable="False"
ToolTip="Show the selected voyage's events"
Visibility="{Binding Data.ViewDefinition.IsInternalView, Converter={StaticResource MwBoolToVisibilityConverterReverse}}">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource Anchor}" />
<TextBlock
Style="{StaticResource MwTextBlockLabelStyle}"
Text="Hide Voyage Events"
Visibility="{Binding IsVoyageEventsShowing, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBlock
Style="{StaticResource MwTextBlockLabelStyle}"
Text="Show Voyage Events"
Visibility="{Binding IsVoyageEventsShowing, Converter={StaticResource MwBoolToVisibilityConverterReverse}}" />
</StackPanel>
</Button>
<Border Grid.Row="0" Grid.Column="8">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDuplicateView, Mode=TwoWay}" Value="true">
<Setter Property="Background" Value="LightGreen" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Button AutomationProperties.AutomationId="DuplicateCheckButton"
Padding="0"
Command="{Binding DuplicateVoyagesCommand}"
Focusable="False"
Style="{StaticResource MwButtonStyle}"
ToolTip="Switch to duplicate Voyages (ALT + D)"
Visibility="{Binding Data.ViewDefinition.IsInternalView, Converter={StaticResource MwBoolToVisibilityConverterReverse}}">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource Duplicate}" />
<AccessText Style="{StaticResource MwAccessTextLabelStyle}" Text="{Binding VoyageDuplicateText}" />
</StackPanel>
</Button>
</Border>
<Button AutomationProperties.AutomationId="PublishVoyagesButton"
Grid.Row="0"
Grid.Column="9"
Padding="0"
Command="{Binding PublishVoyagesCommand}"
Focusable="False"
Style="{StaticResource MwButtonStyle}"
ToolTip="Publish any modified Voyages (ALT + P)"
Visibility="{Binding Data.ViewDefinition.IsInternalView, Converter={StaticResource MwBoolToVisibilityConverterReverse}}">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource Publish}" />
<AccessText Style="{StaticResource MwAccessTextLabelStyle}" Text="{Binding VoyagePublishText}" />
</StackPanel>
</Button>
<Button AutomationProperties.AutomationId="UndoSingleVoyageButton"
Grid.Row="0"
Grid.Column="10"
Padding="0"
Command="{Binding UndoSingleChangedVoyagesCommand}"
Focusable="False"
Style="{StaticResource MwButtonStyle}"
ToolTip="Locally Undo unpublished changes to the selected voyage"
Visibility="{Binding Data.ViewDefinition.IsInternalView, Converter={StaticResource MwBoolToVisibilityConverterReverse}}">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource Undo}" />
<TextBlock Style="{StaticResource MwTextBlockLabelStyle}" Text="Undo Selected" />
</StackPanel>
</Button>
<Button AutomationProperties.AutomationId="UndoandUnpublishVoyageButton"
Grid.Row="0"
Grid.Column="11"
Padding="0"
Command="{Binding UndoChangedVoyagesCommand}"
Focusable="False"
Style="{StaticResource MwButtonStyle}"
ToolTip="Locally Undo any changed and unpublished voyages"
Visibility="{Binding Data.ViewDefinition.IsInternalView, Converter={StaticResource MwBoolToVisibilityConverterReverse}}">
<StackPanel Orientation="Horizontal">
<ContentControl Height="26" Content="{StaticResource Undo}" />
<TextBlock Style="{StaticResource MwTextBlockLabelStyle}" Text="Undo All" />
</StackPanel>
</Button>
</Grid>
</Grid>
</DataTemplate>
</dx:DXTabControl.ItemTemplate>
</dx:DXTabControl>
My FlaUIapproach of locating the Controls is below
public IMainWindow ConfirmCreatedView()
{
_logger.Info("Checking the newly created View on the screen");
//Apoorv: Need to find TabItem here
_controlAction.Highlight(ViewsTabControl); // This highlights the TabControl- Works
int NumberOfActiveTabs = ViewsTabControl.TabItems.Length; // This gives me no of TabItems
TabItem SelectedTab= ViewsTabControl.SelectedTabItem as TabItem; // Gives me Null here
var newTab = ViewsTabControl.SelectedTabItemIndex ; // Give me -1 here
_controlAction.Highlight(ViewsTabControl.TabItems[2]); // Works. It highlights the TabItem at position 2
_controlAction.ClickWait<TabItem>(ViewsTabControl.TabItems[2]); // This goes and clicks the tab item
TabItem SelectedTabs = ViewsTabControl.SelectedTabItem as TabItem;
var check = ViewsTabControl.TabItems[2].FindAllChildren();
// TabItem ti = ViewsTabControl.SelectedItem as TabItem;
//_controlAction.Highlight()
_controlAction.Highlight(CloseCurrentView); // highlights the close button atTabItem[0]
_controlAction.Click<Button>(CloseCurrentView); // closes it
return this;
}
I am using FlaUI to Find the TabControl using AutomationID as shown below
private Tab ViewsTabControl => _uiAutomation.FindElement("ViewsParentTabControl", Automation.FindBy.Id).AsTab();
private TabItem ViewsTabItem => _uiAutomation.FindElement("DXTabItem", Automation.FindBy.Id).AsTabItem();
I would like to find the curently active TabItem based on the Index and then go and click the close button by automating it.
TabItem SelectedTab= ViewsTabControl.SelectedTabItem as TabItem; // Gives me Null here
var newTab = ViewsTabControl.SelectedTabItemIndex ; // Give me -1 here
It is not TabItem it is DXTabItem. This is the type you should cast to.
DXTabItem SelectedTab = ViewsTabControl.SelectedTabItem as DXTabItem;
DevEXpress don't create automation peers for controls within ItemHeaderTemplate. It will be necessary to use a custom automation peer to provide this functionality. For example, I used the following class for test purposes:
public class DXTabItemAutomationPeerEx : DXTabItemAutomationPeer, ISelectionItemProvider {
private DXTabItem TabItem => base.Owner as DXTabItem;
private DXTabControl TabControl => TabItem.With((DXTabItem x) => x.Owner);
public DXTabItemAutomationPeerEx(DXTabItem ownerCore) : base(ownerCore) { }
protected override List<AutomationPeer> GetChildrenCore() {
List<AutomationPeer> children = base.GetChildrenCore();
foreach (var button in LayoutTreeHelper.GetVisualChildren(Owner).OfType<Button>())
children.Add(new ButtonAutomationPeer(button));
return children;
}
bool ISelectionItemProvider.IsSelected { get {
if (TabControl != null) {
return TabControl.SelectedContainer == TabItem;
}
return false;
}
}
}
Post adding this code inside my MainPage.Xaml.cs , I added a static constructor to register it
static MainWindow() {
NavigationAutomationPeersCreator.Default.RegisterObject(typeof(DXTabItem), typeof(DXTabItemAutomationPeerEx), owner => new DXTabItemAutomationPeerEx((DXTabItem)owner));
}
post this , these lines work as charm
TabItem CurrentTab = ViewsTabControl.SelectedTabItem as TabItem;
var Children = ViewsTabControl.FindAllChildren();
foreach (var child in Children) {
var subChildren = child.FindAllChildren();
}

Link a ListBox Borderbrush property to a IsEnabled button

I have two TextBoxes, two ListBoxes, a Cancel button and an OK button.
Simplifying the problem, I would like to link the color of the Borderbrush of the second ListBox to the IsEnabled property of the OK button.
An alternative would be link that color change to the ListBoxItem background instead of the Listbox border itself.
Is it possible (maybe through Triggers or something)? If so, could you show me the way?
The XAML of the window is as follows:
<Window x:Class="Opt.ExpertSystem.View.WindowPasteRules"
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"
mc:Ignorable="d"
xmlns:scroll="clr-namespace:Opt.ExpertSystem.View"
Title="Paste Rules Options" Width="400" Height="300">
<Window.InputBindings>
<KeyBinding Key="Esc" Command="{Binding CancelCommand}" />
</Window.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="100*"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="76*" />
</Grid.ColumnDefinitions>
<Label Content="Select Rules to Paste: " Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" HorizontalContentAlignment="Right" Margin="0,0,2,0" Width="Auto"/>
<Grid Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.Resources>
<Style TargetType="ScrollViewer">
<Setter Property="scroll:ScrollSynchronizer.ScrollGroup" Value="Group1" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Content="Replace" HorizontalAlignment="Stretch" FontWeight="Bold"/>
<TextBox Margin="55,2,2,2" Text="{Binding CopyNameOrigin}" ToolTip="Non-editable field. Represents the text you want to replace." Focusable="False"/>
<Label Content="With" Grid.Column="2" HorizontalAlignment="Stretch" FontWeight="Bold"/>
<TextBox Grid.Column="2" Margin="42,2,2,2" Text="{Binding CopyNameNew, UpdateSourceTrigger=PropertyChanged}" ToolTip="Represents the results of the changes to be made." />
<ListBox ItemsSource="{Binding Path=CopiedRules}" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="0" BorderThickness="1" BorderBrush="CornflowerBlue" Grid.IsSharedSizeScope="True" Margin="2,0,2,10" >
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding Path=PasteRules}" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="2" BorderThickness="1" BorderBrush="CornflowerBlue" Margin="2,0,2,10" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" Margin="2,5,2,5" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
<Grid Grid.Row="2" Background="#FFECE9D8" Grid.ColumnSpan="2">
<Button Content="OK" x:Name="btnOK" IsEnabled="{Binding IsValid, UpdateSourceTrigger=PropertyChanged}" Margin="0,6,6,0" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="75" Height="23" Click="btnOK_Click" />
<Button Content="Cancel" x:Name="btnCancel" IsCancel="True" Margin="0,6,90,0" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="75" Height="23" />
</Grid>
</Grid>
</Window>
Here's a small example that changes the border brush of a listview based on the IsEnabled property of a button
<StackPanel>
<ListBox Height="100">
<ListBox.Style>
<Style TargetType="ListBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=okButton, Path=IsEnabled}" Value="false">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=okButton, Path=IsEnabled}" Value="true">
<Setter Property="BorderBrush" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
<Button IsEnabled="True" Name="okButton">true</Button>
</StackPanel>
But I would set the availability of the button on the command and not in the XAML, also I would bind the color of the ListView to the IsValid property in the ViewModel instead.

Column Headers Offset From Data in Wpf Datagrid

Good morning
I have a Wpf datagrid that is displaying an observable collection of a custom type
I group the data using a collection view source in XAML on two seperate properties, and I have styled the groups to display as expanders.
For clarity, as there is a lot of data I feel I have to use margins and spacing otherwise things look very cluttered.
My problem is that with two levels of hierarchical expanders the column data is now substantially offset from the column headers meaning that they do not properly line up.
I have tried several thing, like setting the margin of the column headers and the width (both actual and normal). However all of my attempts end up resizing the whole column so that the offset stays the same but the columns move.
so my question:
How can I change the visible width or offset of a column header to ensure that the headers line up with the data
Visual Studio 2012
Wpf
C#
DataGrid
EDIT This is what I mean
EDIT 2 - MY Xaml for Grouping
<!-- Style for groups at top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander Margin="5,10,5,5"
BorderBrush="{StaticResource BlackBrush}"
BorderThickness="1"
Header="{Binding Name}"
IsExpanded="True">
<Expander.Template>
<!-- The basic expander -->
<ControlTemplate TargetType="{x:Type Expander}">
<!-- Put a border around the expander -->
<Border Background="{Binding Path=Name,
Converter={StaticResource ColourConverter}}"
BorderBrush="{StaticResource GreyBrush}"
BorderThickness="2"
CornerRadius="3">
<!-- Use a dock panel so that the toggle button is docked to the top and the content is docked to the bottom -->
<DockPanel Margin="0">
<!-- Add the toggle button -->
<ToggleButton x:Name="ExpanderButton"
Margin="0"
Content="{TemplateBinding Header}"
DockPanel.Dock="Top"
FontSize="14"
FontWeight="Bold"
Foreground="{StaticResource BlackBrush}"
IsChecked="{Binding Path=IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
Template="{StaticResource AnimatedExpanderButton}" />
<ContentPresenter x:Name="ExpanderContent"
Margin="5"
ContentSource="Content"
DockPanel.Dock="Bottom"
Visibility="{Binding ElementName=ExpanderButton,
Path=IsChecked,
Converter={StaticResource VisibilityConverter}}" />
</DockPanel>
</Border>
</ControlTemplate>
</Expander.Template>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
<!-- Style for groups under the top level. -->
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Margin" Value="0,0,0,5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander Margin="5"
Background="{Binding Path=Name,
Converter={StaticResource ColourConverter}}"
IsExpanded="True"
Visibility="{Binding Items[0].IsSelectedInSidebar,
Converter={StaticResource VisibilityConverter}}">
<Expander.Template>
<!-- The basic expander -->
<ControlTemplate TargetType="{x:Type Expander}">
<!-- Put a border around the expander -->
<Border Background="{Binding Path=Name,
Converter={StaticResource ColourConverter}}"
BorderBrush="{StaticResource GreyBrush}"
BorderThickness="2"
CornerRadius="3">
<!-- Use a dock panel so that the toggle button is docked to the top and the content is docked to the bottom -->
<DockPanel Margin="0">
<!-- Add the toggle button -->
<ToggleButton x:Name="ExpanderButton"
Content="{Binding Path=Name}"
DockPanel.Dock="Top"
FontSize="12"
IsChecked="{Binding Path=IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
Template="{StaticResource AnimatedExpanderButton}" />
<ContentPresenter x:Name="ExpanderContent"
Margin="5"
ContentSource="Content"
DockPanel.Dock="Bottom"
Visibility="{Binding ElementName=ExpanderButton,
Path=IsChecked,
Converter={StaticResource VisibilityConverter}}" />
</DockPanel>
</Border>
</ControlTemplate>
</Expander.Template>
<Expander.Content>
<Border BorderBrush="{StaticResource BlackBrush}" BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsPresenter Grid.Row="0" Margin="0" />
<Border Grid.Row="1"
Margin="0,10,0,0"
BorderBrush="{StaticResource BlackBrush}"
BorderThickness="0,1,0,0"
Visibility="{Binding Data.SettingRepository.MainDataSummaryVisible,
Source={StaticResource BindingProxy},
Converter={StaticResource VisibilityConverter}}">
<Grid Background="{StaticResource WhiteBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.ColumnSpan="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Margin="5"
FontWeight="Bold"
Text="{Binding Path=Items[0].Option1Title}"
Visibility="{Binding Data.SettingRepository.MainDataShowSampleOptions,
Source={StaticResource BindingProxy},
Converter={StaticResource VisibilityConverter}}" />
<TextBlock Grid.Column="1"
Margin="5"
Text="{Binding Path=Items[0].Option1Data,
Mode=OneWay}"
Visibility="{Binding Data.SettingRepository.MainDataShowSampleOptions,
Source={StaticResource BindingProxy},
Converter={StaticResource VisibilityConverter}}" />
<TextBlock Grid.Column="2"
Margin="5"
FontWeight="Bold"
Text="{Binding Path=Items[0].Option2Title}"
Visibility="{Binding Data.SettingRepository.MainDataShowSampleOptions,
Source={StaticResource BindingProxy},
Converter={StaticResource VisibilityConverter}}" />
<TextBlock Grid.Column="3"
Margin="5"
Text="{Binding Path=Items[0].Option2Data,
Mode=OneWay}"
Visibility="{Binding Data.SettingRepository.MainDataShowSampleOptions,
Source={StaticResource BindingProxy},
Converter={StaticResource VisibilityConverter}}" />
<TextBlock Grid.Column="4"
Margin="5"
FontWeight="Bold"
Text="{Binding Path=Items[0].Option3Title}"
Visibility="{Binding Data.SettingRepository.MainDataShowSampleOptions,
Source={StaticResource BindingProxy},
Converter={StaticResource VisibilityConverter}}" />
<TextBlock Grid.Column="5"
Margin="5"
Text="{Binding Path=Items[0].Option3Data,
Mode=OneWay}" />
<TextBlock Grid.Column="6"
Margin="5"
FontWeight="Bold"
Text="{Binding Path=Items[0].Option4Title}"
Visibility="{Binding Data.SettingRepository.MainDataShowSampleOptions,
Source={StaticResource BindingProxy},
Converter={StaticResource VisibilityConverter}}" />
<TextBlock Grid.Column="7"
Margin="5"
Text="{Binding Path=Items[0].Option4Data,
Mode=OneWay}"
Visibility="{Binding Data.SettingRepository.MainDataShowSampleOptions,
Source={StaticResource BindingProxy},
Converter={StaticResource VisibilityConverter}}" />
<TextBlock Grid.Column="8"
Margin="5"
FontWeight="Bold"
Text="{x:Static languages:Strings.SampleIsAnnealedColumnHeader}" />
<CheckBox Grid.Column="9"
Margin="3,5,5,5"
IsChecked="{Binding Path=Items[0].SampleIsAnnealed,
Mode=OneWay}"
IsHitTestVisible="False"
Style="{StaticResource FandFCheckBox}" />
</Grid>
<!-- The mean Match temperature -->
<TextBlock Grid.Row="1"
Grid.Column="0"
Margin="5"
FontWeight="Bold"
Text="{x:Static languages:Strings.MeanSampleMatchTemperatureTitle}" />
<TextBlock Grid.Row="1"
Grid.Column="1"
Margin="5"
Text="{Binding Path=Items[0].SampleMeanMatchTemperature,
Mode=OneWay,
StringFormat=\{0:N2\}}" />
<!-- The match temperature range -->
<TextBlock Grid.Row="1"
Grid.Column="2"
Margin="5"
FontWeight="Bold"
Text="{x:Static languages:Strings.SampleTemperatureRangeTitle}" />
<TextBlock Grid.Row="1"
Grid.Column="3"
Margin="5"
Text="{Binding Path=Items[0].SampleMatchTemperatureRange}" />
<!-- The match temperature standard deviation -->
<TextBlock Grid.Row="1"
Grid.Column="4"
Margin="5"
FontWeight="Bold"
Text="{x:Static languages:Strings.SampleTemperatureStandardDeviationTitle}" />
<TextBlock Grid.Row="1"
Grid.Column="5"
Margin="5"
Text="{Binding Path=Items[0].SampleMatchTemperatureStandardDeviation,
Mode=OneWay,
StringFormat=\{0:N3\}}" />
<!-- The mean refractive index -->
<TextBlock Grid.Row="2"
Grid.Column="0"
Margin="5"
FontWeight="Bold"
Text="{x:Static languages:Strings.SampleMeanRefractiveIndexTitle}" />
<TextBlock Grid.Row="2"
Grid.Column="1"
Margin="5"
Text="{Binding Path=Items[0].SampleMeanRefractiveIndex,
Mode=OneWay,
StringFormat=\{0:N5\}}" />
<!-- The refractive index range -->
<TextBlock Grid.Row="2"
Grid.Column="2"
Margin="5"
FontWeight="Bold"
Text="{x:Static languages:Strings.SampleRIRangeTitle}" />
<TextBlock Grid.Row="2"
Grid.Column="3"
Margin="5"
Text="{Binding Path=Items[0].SampleRefractiveIndexRange}" />
<!-- The refractive index standard deviation -->
<TextBlock Grid.Row="2"
Grid.Column="4"
Margin="5"
FontWeight="Bold"
Text="{x:Static languages:Strings.SampleRIStandardDeviationTitle}" />
<TextBlock Grid.Row="2"
Grid.Column="5"
Margin="5"
Text="{Binding Path=Items[0].SampleRefractiveIndexStandardDeviation,
Mode=OneWay,
StringFormat=\{0:N7\}}" />
</Grid>
</Border>
</Grid>
</Border>
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
You can set the ColumnHeaderStyle and there set a RenderTransform that moves the headers to the right.
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="RenderTransform">
<Setter.Value>
//change the X value accordingly
<TranslateTransform X="100"></TranslateTransform>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
EDIT 2:
As you mentioned, doing this will result in a small gap. To remove it you should set the left margin of the first column to a negative value, which stretches the header of this column to the left. You can do it like this:
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
//change the margin accordingly
<Setter Property="Margin" Value="-100 0 0 0" />
<Setter Property="RenderTransform">
<Setter.Value>
//change the X value accordingly
<TranslateTransform X="100"></TranslateTransform>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.HeaderStyle>
You have to set the RenderTransform here again, because this style overwrites the general ColumnHeaderStyle. To remove duplication you can add the render transfrom as a resource.
EDIT:
I just saw that you have a few margins on your Expanders and ContentPresenters. If you change them so that you have 0 margin to the left, it would align the content more to the left and reduce the alignment difference.
You would then need less offset on the RenderTransform.
Some examples of your code to illustrate what I mean:
<Expander Margin="5,10,5,5"
<ContentPresenter x:Name="ExpanderContent" Margin="5"
If you change it to
<Expander Margin="0,10,5,5"
<ContentPresenter x:Name="ExpanderContent" Margin="0 5 5 5"
the columns move more to the left.

Red border remains on the TextBox even after the data input is valid

I am writing an app using WPF, WPF Application Framework and MahApps.Metro. I have validation enabled for a data entry window like this:
<controls:MetroWindow x:Class="FinancePlus.Presentations.Views.CustomerView"
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="300" d:DesignWidth="526"
xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:presentation="clr-namespace:System.Waf.Presentation;assembly=WpfApplicationFramework"
presentation:ValidationHelper.IsEnabled="true" presentation:ValidationHelper.IsValid="{Binding IsValid, Mode=OneWayToSource}"
Title="Customer Editor">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colours.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Green.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid DataContext="{Binding Customer}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.Resources>
<Style TargetType="GroupBox">
<Setter Property="Margin" Value="10,5"></Setter>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="0">
<GroupBox Header="Personal Information" DockPanel.Dock="Top">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Content="Title:" Grid.Column="0" Grid.Row="0" Margin="3" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="0" Height="23" Margin="3" Name="titleTextBox"
Text="{Binding Path=Title, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, ValidatesOnDataErrors=True}"
VerticalAlignment="Center" MinWidth="120" />
<Label Content="Full Name:" Grid.Column="0" Grid.Row="1" Margin="3" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="1" Height="23" Margin="3" Name="fullNameTextBox"
Text="{Binding Path=FullName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, ValidatesOnDataErrors=True}"
VerticalAlignment="Center" MinWidth="120" />
<Label Content="Name With Initials:" Grid.Column="0" Grid.Row="2" Margin="3" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="2" Height="23" Margin="4" Name="nameWithInitialsTextBox"
Text="{Binding Path=NameWithInitials, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, ValidatesOnDataErrors=True}"
VerticalAlignment="Center" MinWidth="120" />
<Label Content="Civil Status:" Grid.Column="0" Grid.Row="3" Margin="3" VerticalAlignment="Center" />
<ComboBox DisplayMemberPath="CivilStatus" Grid.Column="1" Grid.Row="3" Height="23"
ItemsSource="{Binding}" Margin="3" Name="civilStatusComboBox" VerticalAlignment="Center" MinWidth="120" HorizontalAlignment="Stretch">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
<Label Content="Date Of Birth:" Grid.Column="0" Grid.Row="4" Margin="3" VerticalAlignment="Center" />
<DatePicker Grid.Column="1" Grid.Row="4" Height="25" Margin="3" Name="dateOfBirthDatePicker" HorizontalAlignment="Right"
SelectedDate="{Binding Path=DateOfBirth, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="115" />
<Label Content="Id Number:" Grid.Column="0" Grid.Row="5" Margin="3" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="5" Height="23" Margin="3" Name="idNumberTextBox"
Text="{Binding Path=IdNumber, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, ValidatesOnDataErrors=True}"
VerticalAlignment="Center" MinWidth="120" />
<Label Content="Profession:" Grid.Column="0" Grid.Row="6" Margin="3" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="6" Height="23" Margin="3" Name="professionTextBox"
Text="{Binding Path=Profession, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, ValidatesOnDataErrors=True}"
VerticalAlignment="Center" MinWidth="120" />
</Grid>
</GroupBox>
..... More code.
The result looks like this:
Which looks nice. The trouble is even when I enter valid values for a TextBox a red border remains. Like you can see in the title and full name TextBoxes here. How do I remove this residue red border? Where is it coming from?
I've come across this before, when it happened to me I had to perform a data change during initialize and ContentRendered. Cause I had the items actually bound.
Another thing I saw awhile ago on Stack Overflow was an issue that happened here that also caused something similar.
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<ControlTemplate.Resources>
<BooleanToVisibilityConverter x:Key="converter" />
</ControlTemplate.Resources>
<DockPanel LastChildFill="True">
<Border
BorderThickness="1"
BorderBrush="Red"
Visibility="{Binding ElementName=placeholder, Mode=OneWay, Path=AdornedElement.IsVisible, Converter={StaticResource converter}}">
<AdornedElementPlaceholder x:Name="placeholder" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
That was my encounter, if that doesn't help I'll attempt to recreate the issue and fix as well. See if I can help you out a little better then describing how I fixed it. But hopefully one of those two suggestions helps you out.
Just let me know, hope it helps.

Failing To Set The Wrap Panel Functionailty On Dynamically generated Groupboxes

Hi buddies :) I am working on a wpf app which deals with groupboxes and wrap panel. Looking at the title, it seems to be simple but after dynamically generating set of groupboxes I am finding it difficult. Here is the scenario:
I have 2 xaml files in my project. One is CodecView.xaml and CodecWidgetView.xaml. I have dynamically generated 4 groupboxes on startup as follows:
CodecView.xaml:
<UserControl.Resources>
<DataTemplate x:Key="CWDataTemplate">
<WrapPanel>
<TextBlock Text="{Binding Description}" Margin="0,0,0,0"/>
<local:CodecWidgetView Margin="5,10,5,5"/>
</WrapPanel>
</DataTemplate>
</UserControl.Resources>
<Grid Grid.Row="0" >
<Grid Name="NumberofCodecs" >
<ItemsControl ItemTemplate="{StaticResource CWDataTemplate}" ItemsSource="{Binding CodecWidgets}"/>
</Grid>
</Grid>
CodecWidgetView.xaml:
<Grid>
<GroupBox Height="Auto" HorizontalAlignment="Stretch" Margin="5,5,5,5" Name="groupBox1" VerticalAlignment="Stretch" Width="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton Name="FrequencyBox" Content="Master" Grid.Column="1" Height="25" Width="50" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0" />
<ComboBox Grid.Column="2" ItemsSource="{Binding ModesList}" SelectedItem="{Binding SelectedModesList, Mode=OneWayToSource}" SelectedIndex="2" Height="23" HorizontalAlignment="Center" Margin="0,0,0,0" Name="comboBox2" VerticalAlignment="Center" Width="80" />
<ComboBox Grid.Column="0" ItemsSource="{Binding FrequencyList}" SelectedItem="{Binding SelectedFrequencyList, Mode=OneWayToSource}" SelectedIndex="0" Height="23" HorizontalAlignment="Center" Margin="0,0,0,0" Name="comboBox1" VerticalAlignment="Center" Width="80" />
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Command="{Binding OneSixBitCommand}" Margin="0" Content="16 Bit" Name="OneSixBit" Height="25" Width="45" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Command="{Binding TwoZeroBitCommand}" Margin="0" Content="20 Bit" Name="TwoZeroBit" Height="25" Width="45" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Command="{Binding TwoFourBitCommand}" Margin="0" Content="24 Bit" Name="TwoFourBit" Height="25" Width="45" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" />
<RadioButton Style="{StaticResource {x:Type ToggleButton}}" Command="{Binding ThreeTwoBitCommand}" Margin="0" Content="32 Bit" Name="ThreetwoBit" Height="25" Width="45" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<Grid Grid.Row="2">
<Label Name="BitDelay" Content="Bit Delay" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,205,0" Height="25" Width="55" />
<Slider Height="23" HorizontalAlignment="Center" Minimum="0.0" Maximum="255.0" TickFrequency="1.0" Margin="95,0,0,0" Name="bitdelayslider" VerticalAlignment="Center" Width="160" />
<TextBox Name="BitDelayValue" IsReadOnly="True" Text="{Binding ElementName=bitdelayslider,Path=Value, StringFormat=0.0}" Width="40" Height="20" Margin="0,0,110,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<Grid Grid.Row="3">
<Label Name="DBGain" Content="DB Gain" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,205,0" Height="25" Width="55" />
<TextBox Name="DBGainValue" IsReadOnly="True" Text="{Binding ElementName=dbgainslider,Path=Value, StringFormat=0.0}" Width="40" Height="20" Margin="0,0,110,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Slider Height="23" HorizontalAlignment="Center" Minimum="0.0" Maximum="59.5" TickFrequency="0.5" Margin="95,0,0,0" Name="dbgainslider" VerticalAlignment="Center" Width="160" />
</Grid>
</Grid>
</GroupBox>
</Grid>
CodecViewModel.cs: is a viewmodel class of CodecView.xaml
public ObservableCollection<CodecWidgetViewModel> CodecWidgets { get; set; }
public CodecViewModel()
{
CodecWidgets = new ObservableCollection<CodecWidgetViewModel>();
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 8 - Dig Mic A" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 9 - Dig Mic B" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 10 - PCM A 3P3V" });
CodecWidgets.Add(new CodecWidgetViewModel { Description = "Location 11 - PCM B 3P3V" });
}
CodecWidgetViewModel.cs: is a viewmodel class of CodecWidgetView.xaml
private string _description;
public string Description
{
get
{
return _description;
}
set
{
_description = value;
OnPropertyChanged("Description");
}
}
This on startup dynamically generates 4 groupboxes one below the other. Since my windowsize is minheight = 300 and minwidth = 300, I have set scrollviewer. Since I have used Wrappanel, When i stretch it, it should behave as expected. That's when width is stretched 2nd groupbox should go to the right side of 1st row and same happens below.
On Startup:
When Width is Stretched:
Expected behaviour:
Thus looking at the expected behaviour, I want to achieve how wrappanel behaves :) Even though I have used wrappanel but it doesn't wrk as expected. Please help :)
You have used a WrapPanel as the panel of each individual item in the ItemsSource, which is not doing what you want.
Instead you have to explicitly tell the ItemsControl to use a WrapPanel as the panel for all of its children.
<ItemsControl ItemTemplate="{StaticResource CWDataTemplate}" ItemsSource="{Binding CodecWidgets}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

Categories

Resources