Bind Button Command in ControlTemplate to SelectedItem from Element in DataTemplate - wpf

I have done some googling and searches and find many questions on StackOverFlow that come close to helping me but all the ideas from them still give me binding expression errors in one form or another with most always mentioning it cannot find the source.
Cannot find source for binding with reference 'ElementName=filesList'.
View that calls control template:
<Expander
DockPanel.Dock="Top"
SnapsToDevicePixels="True"
Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="3" Grid.RowSpan="1"
Header="Files"
IsExpanded="True"
ExpandDirection="Down"
Background="{DynamicResource DynamicFrmBG}" Foreground="{DynamicResource DynamicFrmFG}"
>
<ContentControl
SnapsToDevicePixels="True"
Template="{StaticResource filesTemplate}"
/>
</Expander>
Control Template Code Snippet (Comment in this code is another example of different things I have tried):
<ControlTemplate x:Key="filesTemplate">
<Grid
SnapsToDevicePixels="True"
>
<Grid.RowDefinitions>
<RowDefinition Height="5" />
<RowDefinition Height="Auto" />
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="5" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="5" />
</Grid.ColumnDefinitions>
<ContentControl
SnapsToDevicePixels="True"
Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="2" Grid.RowSpan="1"
Margin="0,0,0,0"
Content="{Binding Files}"
ContentTemplate="{StaticResource filesListTemplate}"
/>
<StackPanel
SnapsToDevicePixels="True"
Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="3" Grid.RowSpan="1"
Orientation="Horizontal"
>
<Button
SnapsToDevicePixels="True"
Foreground="{DynamicResource DynamicFrmFG}"
Margin="0,5,5,5"
Content="Download"
Command="{Binding SelectedItem.Content.DownloadCommand, ElementName=filesList}"
MinWidth="50"
>
<!--Command="{Binding SelectedItem.Content.DownloadCommand, Source={StaticResource ResourceKey=filesListTemplate}, ElementName=filesList}"-->
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{DynamicResource DynamicFrmBGColor}" Offset="0"/>
<GradientStop Color="{DynamicResource DynamicFrmFGColor}" Offset="2"/>
</LinearGradientBrush>
</Button.Background>
</Button>
</StackPanel>
</Grid>
Code snippet for the DataTemplate (The ListView datasource is set to an ObservableCollection and the FilesViewModel contains a Download command):
<DataTemplate x:Key="filesListTemplate">
<ListView
x:Name="filesList"
SnapsToDevicePixels="True"
IsTextSearchEnabled="False"
ItemsSource="{Binding }"
HorizontalContentAlignment="Stretch"
BorderBrush="{DynamicResource DynamicFrmFG}" Foreground="{DynamicResource DynamicFrmFG}" Background="{DynamicResource DynamicFrmBG}"
ItemContainerStyle="{DynamicResource ListViewItemStyle_Gray}"
>
<ListView.View>
<GridView
AllowsColumnReorder="False"
ColumnHeaderContainerStyle="{DynamicResource SpecialityHeader}"
>
<GridViewColumn
Width="200" Header="ID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
SnapsToDevicePixels="True"
FontFamily="Consolas" FontSize="14"
Text="{Binding ID}"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Width="200" Header="File Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
SnapsToDevicePixels="True"
FontFamily="Consolas" FontSize="14"
Text="{Binding Filename}"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Width="250" Header="Uploaded By">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
SnapsToDevicePixels="True"
FontFamily="Consolas" FontSize="14"
Text="{Binding Role}"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Width="200" Header="Uploaded When">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
SnapsToDevicePixels="True"
FontFamily="Consolas" FontSize="14"
Text="{Binding UploadedWhen}"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</DataTemplate>
What I am trying to do is this; Bind the button in my control template to the selected FileViewModel, from the ListView, download command. This command, however, is located up in a DataTemplate. Can someone please assist me in doing this successfully?
Edit at 1705EST: Added the View that calls the control template.

Related

ListView not stretching to fit content WPF XAML

Hey Everyone I am trying to figure out why my content will not stretch horizontally to fit my ListView items. I have HorizontalContentAlignment set to stretch, I used almost this exact layout on a second page and the content stretches on the second page. So not exactly sure what is going on and why the content won't stretch.
Here is a picture of what I am talking about
here is the code
<Border>
<Border.Background>
<ImageBrush ImageSource="/Backgrounds/BlueWaveBackground.jpg"/>
</Border.Background>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" HorizontalAlignment="Center" >
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" TextBlock.TextAlignment="Center">
<Border CornerRadius="10"
Background="{StaticResource ForegroundLightBrush}"
Padding="15 10 15 15"
Width="700"
Margin="50 50 50 0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!--First Last Username-->
<StackPanel Grid.Column="0" HorizontalAlignment="Center">
<TextBlock Text="First Name:" Margin="0 10 10 0" />
<TextBlock Text="Last Name:" Margin="0 14 10 0" />
<TextBlock Text="Username:" Margin="0 16 10 0"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Vertical" >
<TextBox Grid.Row="0" Text="{Binding SelectedUser.FirstName}"/>
<TextBox Text="{Binding SelectedUser.LastName}"/>
<TextBox Text="{Binding SelectedUser.UserName}"/>
</StackPanel>
<!--Email and EmployeeType-->
<StackPanel Grid.Column="2" HorizontalAlignment="Center">
<TextBlock Text="Email:" Margin="95 10 10 0" />
<TextBlock Text="Employee Type:" Margin="10 14 10 0" />
</StackPanel>
<StackPanel Grid.Column="3" Orientation="Vertical" >
<TextBox Grid.Row="0" Text="{Binding SelectedUser.Email}"/>
<TextBox Text="{Binding SelectedUser.EmployeeType}"/>
</StackPanel>
</Grid>
<StackPanel Orientation="Horizontal">
<Button Content="Add New User" Margin="15"/>
<Button Content="Update User" Margin="15"/>
<Button Content="Delete User" Margin="15"/>
<Button Content="Clear User Info" Margin="15"/>
</StackPanel>
<!--Data grid-->
<ListView ItemsSource="{Binding Users}"
SelectedItem="{Binding SelectedUser}"
Margin="0,20,0,0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
MaxHeight="150"
x:Name="List">
<ListView.View>
<GridView AllowsColumnReorder="True" ColumnHeaderToolTip="Users">
<GridViewColumn Header="First Name" Width="Auto" DisplayMemberBinding="{Binding FirstName}"/>
<GridViewColumn Header="Last Name" Width="Auto" DisplayMemberBinding="{Binding LastName}"/>
<GridViewColumn Header="Email" Width="Auto" DisplayMemberBinding="{Binding Email}"/>
<GridViewColumn Header="UserName" Width="Auto" DisplayMemberBinding="{Binding UserName}"/>
<GridViewColumn Header="Employee Type" Width="Auto" DisplayMemberBinding="{Binding EmployeeType}"/>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</Grid>
</Border>
Thanks for any suggestions!
I found the solution. I had to set my border width to auto.
<Border CornerRadius="10"
Background="{StaticResource ForegroundLightBrush}"
Padding="15 10 15 15"
Width="auto"
Margin="50 50 50 0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>

Listbox last element incorrect rendering

I got trouble with the listbox. Please, check the screenshot down there. The last element is kind of "eaten" by the listbox external border (I defined appropriate MaxHeight). Can someone help me?
<DataTemplate x:Key="QCTemplate">
<Grid>
<Expander x:Name="expander" Header="{Binding}">
<Expander.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBox Name="ComponentNameTextBlock" Style="{StaticResource BorderlessTextBoxStyle}" Text="{Binding ComponentName, Mode=TwoWay}" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="1">Количество цитат:</TextBlock>
<TextBlock Name="ComponentVolumeTextBlock" Grid.Column="1" Margin="1" Text="{Binding Volume}" />
</Grid>
</StackPanel>
</DataTemplate>
</Expander.HeaderTemplate>
<!-- Контекстное меню экспандера -->
<Expander.ContextMenu>
<ContextMenu>
<MenuItem Header="Оригинал 'My Clippings.txt'">
<MenuItem Header="Удалить из оригинала..."
Command="{StaticResource ResourceKey=DeleteFromMyClippingsCommand}"
CommandParameter="{Binding}" />
</MenuItem>
</ContextMenu>
</Expander.ContextMenu>
<!-- Внутреннее содержание экспандера -->
<Grid Name="ExpanderContentContainer"
Height="{Binding ElementName=ComponentChildsListBox, Path=ActualHeight}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Rectangle Grid.Column="0" Grid.Row="0"
Width="2" Height="{Binding Path=ActualHeight}"
Fill="Black"
Margin="2"
/>
<StackPanel Orientation="Vertical"
Grid.Column="1" Grid.Row="0">
<TextBox Name="ComponentCommentTextBox"
Text="{Binding Comment, Converter={StaticResource ResourceKey=QCCCommentConvrtr}, Mode=TwoWay}"
BorderThickness="0"
GotFocus="ComponentCommentTextBox_GotFocus"
Margin="1"
/>
<ListBox Name="ComponentChildsListBox"
BorderBrush="Transparent"
ItemsSource="{Binding ChildsCollection}"
ScrollViewer.CanContentScroll="False"
MaxHeight="300"
Margin="1"
Style="{StaticResource LibraryViewListBoxStyle}"
/>
</StackPanel>
</Grid>
</Expander>
</Grid>
</DataTemplate>
Screenshot

How can I wrap a custom text?

I have a listbox that uses datatemplates and one of the elements in the template is a textblock. Problem is that the words won't wrap, and I don't want to set a fixed size. Anybody that knows how to resolve this problem? It's driving me crazy!
<ListBox Grid.Row=" 1" HorizontalContentAlignment="Stretch" Background="#24221f" ItemsSource="{Binding Messages}" ScrollViewer.VerticalScrollBarVisibility="Visible" ClipToBounds="False" BorderBrush="{x:Null}">
<ListBox.ItemTemplate>
<DataTemplate >
<Border BorderBrush="#24221f" BorderThickness="3" Width=" auto">
<DockPanel Background="{StaticResource blackBackground}" HorizontalAlignment="Stretch" Width="auto">
<Border BorderThickness="3" BorderBrush="Transparent">
<Image Source="{Binding IconImageUrl}" VerticalAlignment="top" Height="22" Width ="22" DockPanel.Dock="Left" />
</Border>
<Border BorderThickness="3" BorderBrush="LightGray" Height="auto" Width="auto" HorizontalAlignment="Left" VerticalAlignment="Center" DockPanel.Dock="Left">
<Image Source="{Binding ProfileImageUrl}" VerticalAlignment="Top" HorizontalAlignment="Left" Height="48" Width ="48" />
</Border>
<StackPanel Orientation="Vertical" DockPanel.Dock="Left" Margin="5,0,0,0">
<Label Content="{Binding Path=Sender}" Foreground="#feb41c" FontFamily="Verdana" FontWeight="Bold" FontSize="14" />
<TextBlock Width="100" Text="{Binding Path=ShortMessage}" Margin="10,0,0,0" Foreground="BlanchedAlmond" TextWrapping="Wrap" FontFamily="Verdana" />
<Label Content="{Binding Path=Time}" Margin="10,0,0,0" Foreground="DarkGray" FontFamily="Verdana" FontStyle="Italic"/>
</StackPanel>
</DockPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
StackPanel is Evil :=) when i have strange behaviours in a xaml which include StackPanel, switching to a Grid with right parameters ( fixed sized, or stars or "Auto" ) often fix the issue.
Note also that there is an error in your xaml since you set the DockPanel.Dock of your first image (IconImageUrl) whereas it is in the border that surrrounds it that you should be setting it. That may get the Layout to do strange things.
just try with HorizontalContentAlignment property to "Stretch" of ListBoxItems using the Style
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
and also disable the HorizontalScrollBar visibility
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Update
<Window.Resources>
<SolidColorBrush x:Key="blackBackground" Color="Black"/>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</Window.Resources>
<Grid>
<ListBox Grid.Row=" 1" HorizontalContentAlignment="Stretch" Background="#24221f" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Messages}" ScrollViewer.VerticalScrollBarVisibility="Visible" ClipToBounds="False" BorderBrush="{x:Null}">
<ListBox.ItemTemplate>
<DataTemplate >
<Border BorderBrush="#24221f" BorderThickness="3" Width=" auto">
<DockPanel Background="{StaticResource blackBackground}" HorizontalAlignment="Stretch" Width="auto">
<Border BorderThickness="3" BorderBrush="Transparent">
<Image Source="{Binding IconImageUrl}" VerticalAlignment="top" Height="22" Width ="22" DockPanel.Dock="Left" />
</Border>
<Border BorderThickness="3" BorderBrush="LightGray" Height="auto" Width="auto" HorizontalAlignment="Left" VerticalAlignment="Center" DockPanel.Dock="Left">
<Image Source="{Binding ProfileImageUrl}" VerticalAlignment="Top" HorizontalAlignment="Left" Height="48" Width ="48" />
</Border>
<StackPanel Orientation="Vertical" DockPanel.Dock="Left" Margin="5,0,0,0">
<Label Content="{Binding Path=Sender}" Foreground="#feb41c" FontFamily="Verdana" FontWeight="Bold" FontSize="14" />
<TextBlock Text="{Binding Path=ShortMessage}" Margin="10,0,0,0" Foreground="BlanchedAlmond" TextWrapping="Wrap" FontFamily="Verdana" />
<Label Content="{Binding Path=Time}" Margin="10,0,0,0" Foreground="DarkGray" FontFamily="Verdana" FontStyle="Italic"/>
</StackPanel>
</DockPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I think this thread answer's your question, see the accespted answer by "Nash" - Force TextBlock to wrap in WPF ListBox
( and remember to upvote the answer the the linked thread if it helps you :) )

Button alignment problem in listbox in WPF

I have a listbox containing itemtemplate like this
<ListBox Name="lstCompany" Grid.Column="0" MinWidth="200" Grid.Row="1" HorizontalAlignment="Stretch" Margin="2,2,2,2" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" ItemsSource="{Binding}" SelectionChanged="lstCompany_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<Grid Name="grid1" VerticalAlignment="Top" Margin="2" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding [0]}" FontWeight="Bold" />
<TextBlock Text="{Binding [1]}"></TextBlock>
<StackPanel.ToolTip>
<ToolTip>asdf</ToolTip>
</StackPanel.ToolTip>
</StackPanel>
</Grid>
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Right" DockPanel.Dock="Right">
<Button Content="X" Tag="{Binding [2]}" Width="20" Click="btnRemove_Click" Name="btnRemove1" HorizontalAlignment="Right"></Button>
</StackPanel>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This listbox is in first column of a grid which has a splitter.
Now problem is that I am not able to align the button to right side of listbox item.
One Grid is enough here. You only need one star-sized column (for content) and one Auto-sized column (for the button):
<ListBox Name="lstCompany" Grid.Column="0" MinWidth="200" Grid.Row="1" HorizontalAlignment="Stretch" Margin="2,2,2,2" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" ItemsSource="{Binding}" SelectionChanged="lstCompany_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate >
<Grid Name="grid1" VerticalAlignment="Top" Margin="2" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding [0]}" FontWeight="Bold"/>
<TextBlock Text="{Binding [1]}" ></TextBlock>
<StackPanel.ToolTip>
<ToolTip>asdf</ToolTip>
</StackPanel.ToolTip>
</StackPanel>
<StackPanel Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Right">
<Button Content="X" Tag="{Binding [2]}" Width="20" Click="btnRemove_Click" Name="btnRemove1"></Button>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

WPF: ComboBoxItem background

I have a ComboBox based on XML file data:
<Root>
<Node Background="Yellow" Foreground="Cyan" Image="1.ico" Property="aaaa" Value="28" />
<Node Background="SlateBlue" Foreground="Black" Image="2.ico" Property="bbbb" Value="2.5" />
<Node Background="Teal" Foreground="Green" Image="3.ico" Property="cccc" Value="4.0" />
<Node Background="Yellow" Foreground="Red" Image="4.ico" Property="dddd" Value="0" /></Root>
So, in this case, I need to create a compound ComboBoxItem when each item has a suitable background.
I tried to do something like this:
<UserControl.Resources>
<DataTemplate DataType="Node">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" MinWidth="20"/>
</Grid.ColumnDefinitions>
<Border Background="{Binding XPath=#Background}" Grid.Column="0">
<Image Source="{Binding XPath=#Image}"
Width="16"
Height="16"
Margin="3" />
</Border>
<Border Background="{Binding XPath=#Background}" Grid.Column="1">
<TextBlock Foreground="{Binding XPath=#Foreground}"
Margin="3"
Text="{Binding XPath=#Property}" />
</Border>
<Border Background="{Binding XPath=#Background}" Grid.Column="2">
<TextBlock Foreground="{Binding XPath=#Foreground}"
Margin="3"
FontWeight="Bold"
Text="{Binding XPath=#Value}" />
</Border>
</Grid>
</DataTemplate>
<XmlDataProvider x:Key="xmlNodeList"
Source="/data/Combo.xml"
XPath="/Root/Node"/>
</UserControl.Resources>
<ComboBox Name="myComboBox"
ItemsSource="{Binding Source={StaticResource xmlNodeList}}"
SelectedIndex="0" />
but it's not looks good :-(
What solution you recommend?
Thanks in advance!
One thing is that you forgot to indicate which template to use:
<DataTemplate x:Key="Node">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" MinWidth="20"/>
</Grid.ColumnDefinitions>
<Border Background="{Binding XPath=#Background}" Grid.Column="0">
<Image Source="{Binding XPath=#Image}"
Width="16"
Height="16"
Margin="3" />
</Border>
<Border Background="{Binding XPath=#Background}" Grid.Column="1">
<TextBlock Foreground="{Binding XPath=#Foreground}"
Margin="3"
Text="{Binding XPath=#Property}" />
</Border>
<Border Background="{Binding XPath=#Background}" Grid.Column="2">
<TextBlock Foreground="{Binding XPath=#Foreground}"
Margin="3"
FontWeight="Bold"
Text="{Binding XPath=#Value}" />
</Border>
</Grid>
</DataTemplate>
And then your ComboBox:
<ComboBox Name="myComboBox"
ItemsSource="{Binding Source={StaticResource xmlNodeList}}"
ItemTemplate="{StaticResource Node}"
SelectedIndex="0" />
The "dataType" system works with typed object, I'm not sure you can make it work with XML data. This will work.
Update:
Before you ask, you should also define a Style for the items so that they cove the width of the list, otherwise your columns are going to be uneven:
<ComboBox Name="myComboBox"
ItemsSource="{Binding Source={StaticResource xmlNodeList}}"
ItemTemplate="{StaticResource Node}"
SelectedIndex="0">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
This will stretch the individual items to cover the whole width of the list.

Resources