MultiBinding and ContentPresenter - c#

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?

Related

Adding a label to an ItemsControl

Visual presentation is not my strong side when it comes to programming. I'm developing a small program for my company, ment to aid in a schedule overview (can also be described as a timeline).
The background works work as expected, so I don't include this code here as it's not a question of why it's not displaying this data or so. My questions are more on how to present it visually better.
The timeline shows up as a gray bar and is then populated with buttons on the timeline where an event is taking place.
I would like your advice on how I can:
Add a label to the left of the gray bar.
Add a visual timeline (i.e. timestamps) as a gradient above the gray bar, so it visually presents where in the timeline is 3 o'clock and where is 6 o'clock.
or, i would appriciate some advice on where I can read more about it, a hint in the right direction.
Thank you!
<Window x:Class="Test.BookingOverview"
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:Test"
mc:Ignorable="d"
Title="Bokningsöversikt" Height="450" Width="800">
<Window.Resources>
<local:EventLengthConverter x:Key="mEventLengthConverter"/>
</Window.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding Path=TimeLines}" Margin="10,90,10,27" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl x:Name="TimeLine" ItemsSource="{Binding Path=Events}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid x:Name="EventContainer" Height="20" Margin="5" Background="Gainsboro">
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Grid.Column="1" Background="Yellow" VerticalAlignment="Stretch" HorizontalAlignment="Left">
<Button.Margin>
<MultiBinding Converter="{StaticResource mEventLengthConverter}">
<Binding ElementName="TimeLine" Path="DataContext.Duration"/>
<Binding Path="Start"/>
<Binding ElementName="EventContainer" Path="ActualWidth"/>
</MultiBinding>
</Button.Margin>
<Button.Width>
<MultiBinding Converter="{StaticResource mEventLengthConverter}">
<Binding ElementName="TimeLine" Path="DataContext.Duration"/>
<Binding Path="Duration"/>
<Binding ElementName="EventContainer" Path="ActualWidth"/>
</MultiBinding>
</Button.Width>
<Button.Content>
<TextBlock Text="{Binding customer}"></TextBlock>
</Button.Content>
<Button.ContextMenu>
<ContextMenu Name="Test">
<MenuItem Header="Testar contextmenu"></MenuItem>
<Separator></Separator>
<MenuItem Header="Testar igen"></MenuItem>
</ContextMenu>
</Button.ContextMenu>
<Button.ToolTip>
<ToolTip Content="Testar"></ToolTip>
</Button.ToolTip>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Aepot got me in the right direction, but currently it's creating rows of labeling and then the acctual timelines. Most likely due to something I din't understand by using ItemsControls.
Changes made to the code according to the suggestion of Aepot:
<StackPanel Orientation="Vertical" Margin="90,123,0,0">
<TextBlock Text="Bokningsöversikt"></TextBlock>
<ItemsControl ItemsSource="{Binding Path=TimeLines}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl x:Name="TimeLine" ItemsSource="{Binding Path=Events}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid x:Name="EventContainer" Grid.Column="2" Height="20" Margin="5" Background="Gainsboro"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="10" Margin="0,0,0,0" Padding="10,0,0,0" Grid.Column="1" Background="Transparent" VerticalAlignment="Center" HorizontalAlignment="Left">
<TextBlock.Text>
<Binding ElementName="EventContainer" Path="DataContext.RegNr"/>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl ItemsSource="{Binding Path=TimeLines}" >
<ItemsControl.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding RegNr}"/>
<Separator></Separator>
<MenuItem Header="Test"></MenuItem>
</ContextMenu>
</ItemsControl.ContextMenu>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl x:Name="TimeLine" ItemsSource="{Binding Path=Events}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid x:Name="EventContainer" Grid.Column="2" Height="20" Margin="5" Background="Gainsboro"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Grid.Column="2" Background="Yellow" VerticalAlignment="Stretch" HorizontalAlignment="Left">
<Button.Margin>
<MultiBinding Converter="{StaticResource mEventLengthConverter}">
<Binding ElementName="TimeLine" Path="DataContext.Duration"/>
<Binding Path="Start"/>
<Binding ElementName="EventContainer" Path="ActualWidth"/>
</MultiBinding>
</Button.Margin>
<Button.Width>
<MultiBinding Converter="{StaticResource mEventLengthConverter}">
<Binding ElementName="TimeLine" Path="DataContext.Duration"/>
<Binding Path="Duration"/>
<Binding ElementName="EventContainer" Path="ActualWidth"/>
</MultiBinding>
</Button.Width>
<Button.Content>
<TextBlock Text="{Binding customer}"></TextBlock>
</Button.Content>
<Button.ContextMenu>
<ContextMenu Name="Test">
<MenuItem Header="Testar contextmenu"></MenuItem>
<Separator></Separator>
<MenuItem Header="Testar igen"></MenuItem>
</ContextMenu>
</Button.ContextMenu>
<Button.ToolTip>
<ToolTip Content="Testar"></ToolTip>
</Button.ToolTip>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
Note: use TextBlock instead of Label in case of displaying text because it's better optimized for that.
Try wrapping the controls with StackPanel.
<DockPanel>
<TextBlock Text="My timeline"/>
<StackPanel Orientation="Vertical">
<ItemsControl .../><!-- with TextBlocks for labeling timeline -->
<ItemsControl .../><!-- existing one -->
</StackPanel>
</DockPanel>
You can also use StackPanel as Control to use in ItemsPanelTemplate.
Or this way, more friendly if you're familiar with HTML <table>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.RowSpan="2" Text="My timeline"/>
<ItemsControl Grid.Column="1" .../><!-- with TextBlocks for labeling timeline -->
<ItemsControl Grid.Column="1" Grid.Row="1" .../><!-- existing one -->
</Grid>

WPF: Align TextBlock with different font sizes at top

I need to align two text elements of different font sizes at the top line.
All I managed so far is either this :
Resulting from this code:
<Canvas VerticalAlignment="Center" HorizontalAlignment="Center" SnapsToDevicePixels="True">
<StackPanel x:Name="RemainingTimeDisplay" Orientation="Horizontal" VerticalAlignment="Top">
<StackPanel.Margin>
<MultiBinding Converter="{StaticResource CenterConverter}">
<Binding ElementName="RemainingTimeDisplay" Path="ActualWidth"/>
<Binding ElementName="RemainingTimeDisplay" Path="ActualHeight"/>
</MultiBinding>
</StackPanel.Margin>
<!--<Run FontSize="360" Text="{Binding RemainingTime.Minutes, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, StringFormat=D2, Converter={StaticResource IntAbsConverter}}"/>
<Run FontSize="128" Text="{Binding RemainingTime.Seconds, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, StringFormat=D2, Converter={StaticResource IntAbsConverter}}"/>-->
<TextBlock FontSize="360" Text="{Binding RemainingTime.Minutes, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, StringFormat=D2, Converter={StaticResource IntAbsConverter}}"/>
<TextBlock FontSize="128" Text="{Binding RemainingTime.Seconds, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, StringFormat=D2, Converter={StaticResource IntAbsConverter}}"/>
</StackPanel>
</Canvas>
Or:
<Canvas VerticalAlignment="Center" HorizontalAlignment="Center" SnapsToDevicePixels="True">
<StackPanel x:Name="RemainingTimeDisplay" Orientation="Horizontal" VerticalAlignment="Top">
<StackPanel.Margin>
<MultiBinding Converter="{StaticResource CenterConverter}">
<Binding ElementName="RemainingTimeDisplay" Path="ActualWidth"/>
<Binding ElementName="RemainingTimeDisplay" Path="ActualHeight"/>
</MultiBinding>
</StackPanel.Margin>
<TextBlock FontFamily="Roboto" VerticalAlignment="Top">
<TextBlock FontSize="360" Text="{Binding RemainingTime.Minutes, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, StringFormat=D2, Converter={StaticResource IntAbsConverter}}"/>
<TextBlock FontSize="128" Text="{Binding RemainingTime.Seconds, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged, StringFormat=D2, Converter={StaticResource IntAbsConverter}}"/>
</TextBlock>
</StackPanel>
</Canvas>
I tried also some more things, that I don't repeat here in code. I tried using "run" as a child of on single TextBlock for both text elements and I (actually started) tried without the TextBlock that encloses the other two.
So I tried a lot, I googled a lot - and I'm still not where I want to be.
Any hint would be really appreciated!
Thanks,
Marcus
Try the following:
<TextBlock FontSize="360"
Text="00"
LineHeight="360"
LineStackingStrategy="BlockLineHeight" />
<TextBlock FontSize="128"
LineHeight="360"
LineStackingStrategy="BlockLineHeight">
<Run Text="00" BaselineAlignment="Top" />
</TextBlock>

Binding background of datatemplate in contentcontrol

I am trying to bind the background color of a TextBox and use a converter. However, I can't figure out the correct binding due to the TextBox being in a DataTemplate and in a ContentControl.
The DebuggingConverter doesn't fire unless I set the binding path from Path=StateColor to Path=.
Here is the xaml :
<GridViewColumn Header="Value" Width="{Binding SelectedDeviceCol2, Source={x:Static properties:Settings.Default}, Mode=TwoWay}" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding Path=Value, Mode=TwoWay}" IsEnabled="{Binding Path=ReadOnly, Converter={StaticResource readOnlyToEnabledConverter}}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type viewModels:VMDeviceCommand}">
<Button Content="{Binding Name}" Height="24" IsEnabled="True" Click="Button_Click_GetObjectProperty"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:DateTime}">
<DatePicker SelectedDate="{Binding Path=.}"
SelectedDateFormat="Short"
FirstDayOfWeek="Monday"
IsTodayHighlighted="True" >
</DatePicker>
</DataTemplate>
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding Path=.}" TextChanged="TextBox_OnTextChanged">
<TextBox.Background>
<SolidColorBrush Color="{Binding RelativeSource={RelativeSource AncestorType=ContentControl}, Path=StateColor, Converter={StaticResource DebuggingConverter}}"/>
</TextBox.Background>
</TextBox>
</DataTemplate>
<DataTemplate DataType="{x:Type System:UInt16}">
<xctk:IntegerUpDown Text="{Binding Path=.}" ValueChanged="UpDownBase_OnValueChanged" >
</xctk:IntegerUpDown>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Boolean}">
<CheckBox IsChecked="{Binding Path=.}" Click="CheckBox_Click"/>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DataTemplate>
</GridViewColumn.CellTemplate>
ContentControl doesn't have a StateColor property, so the Binding never gets its value and never has anything to pass to a converter.
If the ContentControl's DataContext has a StateColor property, that's easy:
<SolidColorBrush
Color="{Binding DataContext.StateColor, RelativeSource={RelativeSource AncestorType=ContentControl}, Converter={StaticResource DebuggingConverter}}"
/>

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>

Categories

Resources