Binding to a CollectionViewSource returns DependencyProperty.UnsetValue - c#

I need to make an item checked whether it is in use or not by a member of a collection.
When I bind directly to the collection (binding 2) it does work but not through a view of it (binding 3), it returns DependencyProperty.UnsetValue.
Why isn't it working ?
<ListBox.ItemTemplate>
<DataTemplate DataType="system:String">
<StackPanel Orientation="Horizontal">
<CheckBox>
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource AssetToBooleanConverter}" Mode="OneWay" >
<Binding />
<Binding Path="Assets" Source="{StaticResource Singleton}" />
<Binding Source="{StaticResource CvsAssets}" />
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
<TextBlock
Text="{Binding Converter={StaticResource PathToNameConverter}}"
ToolTip="{Binding Converter={StaticResource PathToSizeConverter}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Here is the view of that collection :
<CollectionViewSource x:Key="CvsAssets"
IsLiveSortingRequested="True"
Source="{Binding Source={StaticResource Singleton},
Path=Assets}"
d:IsDataSource="True">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription Converter="{StaticResource ObjectToTypeNameConverter}" />
</CollectionViewSource.GroupDescriptions>
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription PropertyName="Name" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>

I've just fixed it using the following syntax :
<Binding Source="{StaticResource CvsAssets}" Path="(CollectionView.SourceCollection)" />
(Debugger gave a warning about the binding and the type which was ListCollectionView)

Related

How to simplify verbose WPF DataGrid Xaml?

I have a WPF DataGrid with many columns (below I showed only 3 columns for simplicity). To mark up a single column it takes almost 20 lines of code and it repeats for every column. The only difference between the columns is the header text and the binding.
MainView.xaml:
<Window x:Class="UserInterface.MainView"
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:Converters="clr-namespace:UserInterface.Converters"
xmlns:UiUtilities="clr-namespace:.UserInterface.UIUtilities"
mc:Ignorable="d"
Icon="Application.ico"
Title="{Binding WindowTitle}"
SizeToContent="WidthAndHeight"
ResizeMode="NoResize"
DataContext="{Binding MainViewModel}">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
<Converters:VisibleIfOfTypeXConverter x:Key="VisibleIfOfTypeX" />
</Window.Resources>
<DataGrid ItemsSource="{Binding DataModel}" HeadersVisibility="Column" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Header1">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="UserInterface:SomeType">
<Grid>
<TextBox Visibility="{Binding Converter={StaticResource VisibleIfOfTypeX}}">
<TextBox.Text>
<Binding Path="P1Text" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<UiUtilities:NumberRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Header2">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="UserInterface:SomeType">
<Grid>
<TextBox Visibility="{Binding Converter={StaticResource VisibleIfOfTypeX}}">
<TextBox.Text>
<Binding Path="P2Text" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<UiUtilities:NumberRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Header3">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="UserInterface:SomeType">
<Grid> <TextBox Visibility="{Binding Converter={StaticResource VisibleIfOfTypeX}}">
<TextBox.Text>
<Binding Path="P3Text" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<UiUtilities:NumberRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Window>
I'm still a beginner in WPF, but I assume there must be a less verbose way to implement this. I imagine there must be some sort of "templating" or components as they are used in other UI Frameworks.
Could we create some sort of component (I call it "MyCustomDataGridColumn"), that we could use like this:
<DataGrid ItemsSource="{Binding DataModel}">
<DataGrid.Columns>
<MyCustomDataGridColumn Header="Header1" TextBoxBinding="P1Text">
<MyCustomDataGridColumn Header="Header2" TextBoxBinding="P2Text">
<MyCustomDataGridColumn Header="Header3" TextBoxBinding="P3Text">
</DataGrid.Columns>
</DataGrid>
How could we achieve this? Or are there other/better ways to reduce verbosity?

How to bind a template element property in DataTemplate

I want to let a template element property create a binding with another element property, but I found a lot articles and none of them talk about. So I ask for what should I do.
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:StringsJoinConverter x:Key="join_converter" />
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource SampleDataSource}}">
<ListBox ItemsSource="{Binding Collection}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="5">
<StackPanel Orientation="Horizontal">
<TextBlock Background="#FF83C9A9" >
<TextBlock Text="Name:"> </TextBlock>
<TextBox Width="50" x:Name="input_name"></TextBox>
</TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Background="#FFB683C9" >
<TextBlock Text="Value:"> </TextBlock>
<TextBox Width="50" x:Name="input_value"></TextBox>
</TextBlock>
</StackPanel>
<TextBlock >
<TextBlock.Text>
<MultiBinding Converter="{StaticResource join_converter}">
<Binding>
<!--Bind input_name.Text-->
</Binding>
<Binding>
<!--Bind input_value.Text-->
</Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
enter image description here
You can directly bind CompplexProperty.PartA and PartB also you can use ElementName method, In the
below code you can see the both ways also.
<TextBlock >
<TextBlock.Text>
<MultiBinding Converter="{StaticResource join_converter}">
<Binding ElementName="ATextblock" Path="Text">
</Binding>
<Binding Path="ComplexProperty.PartB">
</Binding>
</MultiBinding>
</TextBlock.Text>
</TextBlock>

DependencyProperty.UnsetValue using template and MultiBinding

Anyone knows why I receive the error: "DependencyProperty.UnsetValue" when I call my Command through the Template
This is my template:
<DataTemplate x:Key="MenuComboBoxItemTemplate" DataType="ComboBox">
<DockPanel>
<TextBlock DockPanel.Dock="Left" Text="{Binding Text.Display}" />
<Button x:Name="RemoveButton"
Style="{StaticResource DeleteButton}"
DockPanel.Dock="Right"
ToolTip="Delete"
HorizontalAlignment="Right"
Padding="2"
Margin="3,0,0,0"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl},AncestorLevel=1}, Path=DataContext.RemoveMenuItemCommand}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource MultiValueConverter}">
<Binding Path="Name" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type menus:MenuComboBox}}" />
<Binding />
</MultiBinding>
</Button.CommandParameter>
<Image Source="{dx:DXImageOffice2013 Image=Delete_16x16.png}" />
</Button>
</DockPanel>
</DataTemplate>
My combobox:
<menus:MenuComboBox
x:Name="MyItems"
Grid.Column="0"
Grid.Row="2"
Padding="6,3,5,3"
BorderThickness="1"
Text="{Binding MyItems, UpdateSourceTrigger=LostFocus}"
ItemTemplate="{StaticResource MenuComboBoxItemTemplate}"
ItemsSource="{Binding Menus[MyItems].Items}"
NewMenuItemCommand="{Binding AddMenuItemCommand}"
GotFocusCommand="{Binding GotFocusCommand}" />
I am stuck on it :(

SelectedItem changes textblock variables

I want to get all the data from an Object used as ObservableCollection in a ListView. The ListView is working properly I want to when the Item is selected the information in a TextBlock (outside the ListView) to update with the info that the object as.
How can I do it? What I'm doing wrong?
So to the code:
<ListView
x:Name="dataGrid"
ItemsSource="{Binding Friends}"
Height="586"
BorderThickness="0"
SelectedItem="{Binding SelectedItemFriends,Mode=TwoWay}"
HorizontalAlignment="Left" Width="460">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="Resources\Images\ic_status.png" Height="24" Width="18"/>
<StackPanel Margin="5" Orientation="Vertical">
<TextBlock FontWeight="Bold" Text="{Binding name}"/>
<StackPanel x:Name="RemoveItems" Margin="5" Orientation="Vertical">
<TextBlock Text="{Binding lastLocation, StringFormat='Location: {0}'}"/>
<TextBlock Text="{Binding timestamp}"/>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel x:Name="AdditionItems" Margin="5" Orientation="Vertical" Visibility="Visible">
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myConverter}">
<Binding ElementName="dataGrid" Path="loc.country"/>
<Binding ElementName="dataGrid" Path="loc.area"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
You should specify SelectedItem property in your binding:
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myConverter}">
<Binding ElementName="dataGrid" Path="SelectedItem.loc.country"/>
<Binding ElementName="dataGrid" Path="SelectedItem.loc.area"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>

MultiBinding and ContentPresenter

This is my code of ContentPresenter:
<ListBox ItemsSource="{Binding Items}" BorderThickness="0" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentPresenter x:Name="PART_ValueContainer">
<ContentPresenter.Content>
<MultiBinding>
<Binding Path="Value"/>
<Binding Path="ReadOnly"/>
</MultiBinding>
</ContentPresenter.Content>
<ContentPresenter.Resources>
<DataTemplate>
<TextBox IsReadOnly="{Binding Path=Content.ReadOnly, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
Text="{Binding Path=Content.Value, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
TextAlignment="Left"/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I trying to fill the Text from object Items.Value and property IsReadOnly from Items.ReadOnly.
It doesn't work, I know that is not good solution, but, how to make something like that?

Categories

Resources