How do I add more options in a generic Combo Box - c#

I want to have a combobox like this:
But in code there is no way of doing it. I'm using MVVM pattern. So I have a view:
<ComboBox Style="{StaticResource ComboStyle}" ItemsSource="{Binding ResultObjects}" SelectedItem="{Binding SelectedObject,Mode=TwoWay}" />
and ViewModel:
public IEnumerable<DateTime> ResultObjects { get;set; }
public DateTime SelectedObject{ get;set; }
The fact is that the -All- and -custom- are not DateTime. And it can't be in added to this list.
I remember that in MVC we had a "Dropdown helper".
What can I do here in MVVM?

You could bind to an IEnumerable<KeyValuePair<DateTime?, string>> where the key represent the actual value and the value represents a custom string representation of that value:
public IEnumerable<KeyValuePair<DateTime?, string>> ResultObjects { get; set; }
public DateTime? SelectedObject { get; set; }
...
ResultObjects = new List<KeyValuePair<DateTime?, string>>()
{
new KeyValuePair<DateTime?, string>(null, "All"),
new KeyValuePair<DateTime?, string>(new DateTime(2018,04,17), new DateTime(2018,04,17).ToString("yyyy/MM/dd")),
new KeyValuePair<DateTime?, string>(new DateTime(2018,04,17), new DateTime(2018,04,17).ToString("yyyy/MM/dd # HH:mm:ss")),
new KeyValuePair<DateTime?, string>(new DateTime(2018,04,17), "Custom...")
};
...
XAML:
<ComboBox
ItemsSource="{Binding ResultObjects}"
SelectedValue="{Binding SelectedObject}"
DisplayMemberPath="Value"
SelectedValuePath="Key"/>
Obviosuly you cannot return anything but actual DateTime values from an IEnumerable<DateTime> to you should change the type of your source collection if you want to be able to represent other types of values as well.

The way I'd handle this is to define an ObservableCollection<object>.
When wpf comes across an object presented to the ui it first looks to see if it's got a template defined for the thing. If it hasn't, it will use ToString on the object. You can rely on that for simple cases and override .ToString() on any object you want to use.
If you want more sophisticated display than just a string then you can define a datatemplate which targets your objects based on their datatype.
One trick which can be handy.
You can even inherit from one base object and define a template for that, then more specific ones for sub types. A sub type inheriting from your base object will be dealt with by your "default".
Eg.
I have a map editor. The user is selecting from different terrains he's going to draw. I want to display different stuff for these. I have a BaseTerrainVM and then I inherit from that for river, contour, woods etc.
Here's a subset of the markup I use to template the items in a listbox:
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:BaseTerrainVM}">
<Grid>
<TextBlock Text="{Binding DisplayType}" HorizontalAlignment="Left"
VerticalAlignment="Center"/>
<TextBlock Text="{Binding ID}"
HorizontalAlignment="Right"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ContourVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding DisplayType}"
Grid.Column="0"
VerticalAlignment="Center"/>
<StackPanel Orientation="Horizontal"
Grid.Column="1"
TextElement.FontFamily="Century Gothic"
TextElement.FontSize="{DynamicResource LargeFont}"
TextElement.FontWeight="Normal"
>
<TextBox MinWidth="50"
Text="{Binding Height}"
GotKeyboardFocus="TextBox_GotKeyboardFocus"
>
<i:Interaction.Behaviors>
<ui:TextBoxDecimalRangeBehaviour MaxDecimals="0"
MaxInteger="3"
Minimum="{StaticResource Zero}"
Maximum="{StaticResource TwoFiveFive}" />
<ui:SelectAllTextBoxBehavior/>
</i:Interaction.Behaviors>
</TextBox>
<TextBlock Text="units"
Margin="2,0,0,0"
ToolTip="Elevation is represented by a number 0-255 which is multiplied by a factor to give metres"
/>
</StackPanel>
<TextBlock Text="{Binding ID}"
Grid.Column="2"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:RiverVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding DisplayType}"
Grid.Column="0"
VerticalAlignment="Center"/>
<StackPanel Orientation="Horizontal"
Grid.Column="1"
TextElement.FontFamily="Century Gothic"
TextElement.FontSize="{DynamicResource LargeFont}"
TextElement.FontWeight="Normal"
>
<Button
Command="{Binding PressureFromStartCommand}"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Height="20"
ToolTip="Widen from Start of stroke"
>
<Path Data="{StaticResource FlowRight}"
Stretch="Uniform"
Fill="LightBlue"
Stroke="DodgerBlue"
StrokeThickness="1"
/>
</Button>
<Button
Command="{Binding PressureConstantCommand}"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Height="20"
ToolTip="Constant width for river"
>
<Rectangle
Width="18"
Height="6"
Fill="LightBlue"
Stroke="DodgerBlue"
StrokeThickness="1"
/>
</Button>
<Button
Command="{Binding PressureFromEndCommand}"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Height="20"
ToolTip="Widen from End of stroke"
>
<Path Data="{StaticResource FlowRight}"
Stretch="Uniform"
Fill="LightBlue"
Stroke="DodgerBlue"
StrokeThickness="1"
RenderTransformOrigin="0.5,0.5"
>
<Path.RenderTransform>
<ScaleTransform ScaleX="-1" ScaleY="1" />
</Path.RenderTransform>
</Path>
</Button>
</StackPanel>
<TextBlock Text="{Binding ID}"
Grid.Column="2"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:BoundaryVM}">
<Grid>
( This may amuse Muds. )
My Terrains that presents these is actually a composite collection. In my case this is because I translate all the water on the map into one object so there's no border between one road and the next or a lake and the river flowing into it. I need to present the two representations of water but switch between them.

You need to use CompositeCollection, that can handle more than one collection/s and other objects.
Try something like this
<ComboBox>
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem Content="--All--" />
<CollectionContainer Collection="{Binding Source=ResultObjects}" />
<ComboBoxItem Content="--Custom--" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>

Related

Filter in binding to CollectionViewSource in WPF

I'm doing some fixes in a project where I need to edit an entity named Tariff, which have as a property a collection of TariffSteps. The model was made with Entity Framework Code First:
namespace pbxControl.model.Classes
{
public class Tariff : PropertyChangedNotifier
{
public int TariffId { get; set; }
public string Description { get; set; }
// ...
public ObservableCollection<TariffStep> TariffSteps { get; set; }
// ...
}
public class TariffStep : PropertyChangedNotifier
{
public int TariffStepId { get; set; }
[DefaultValue(0)]
public int Duration { get; set; }
// ...
#region references
public virtual ObservableCollection<Tariff> Tariffs { get; set; }
// ...
Which created a many to many relationship in the DB through an intermediate table "TariffStepTariffs".
In the UI the interface is based in a master - detail scenario where an outer grid is binded to a CollectionViewSource (on tariff collection), inside that grid there is a Datagrid where the tariffs are shown (master), and another grid where the selected tariff is detailed.
Originally, before the new fixes were implemented, the way of dealing with the tariffSteps was as follow: an area for add / remove/ modify TariffSteps in the Model (TariffStepsGrid), and another area where the client could add tariffSteps from the first area to a Tariff (TariffTariffStepsGrid). The idea was that several tariff could share the same step if they have the same properties:
previous way of assign tariffSteps to tariff
<TabItem Name="Tariff_Tab" HorizontalAlignment="Left" TabIndex="5" Header="Tarifas" Style="{StaticResource HorizontalTab}">
<Grid x:Name="TariffsGrid" DataContext="{Binding Source={StaticResource tariffViewSource}}">
<Grid x:Name="TariffDetailGrid" Grid.Row="0" Grid.Column="0" DataContext="{Binding}">
<Grid x:Name="TariffDetailPropertiesGrid" Grid.Row="0" Grid.Column="0" DataContext="{Binding}">
<!-- Some controls for properties of the Tariff -->
</Grid>
<Grid x:Name="CurrencyGrid" Grid.Row="0" Grid.Column="1" DataContext="{StaticResource currencyViewSource}">
<!-- This grid is for management of another entity (Currency) -->
</Grid>
<Grid Grid.Row="1" Grid.Column="0" x:Name="TariffTariffStepsGrid" HorizontalAlignment="Right">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="360"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Grid x:Name="TariffTariffStep" Grid.Column="0" DataContext="{Binding Path=TariffSteps}" HorizontalAlignment="Right">
<ListBox x:Name="TariffStepList1" ItemsSource="{Binding}" HorizontalAlignment="Right" VerticalAlignment="Top"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left" Height="130" Width="200" Margin="0 15 0 5"
TabIndex="22">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="2 2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=DurationV, Mode=TwoWay}" Grid.Column="0" Width="60" TextAlignment="Left"/>
<TextBlock Text="{Binding Path=PeriodV, Mode=TwoWay}" Grid.Column="1" Width="60" TextAlignment="Center"/>
<TextBlock Text="{Binding Path=CostV, Mode=TwoWay}" Grid.Column="2" Width="60" TextAlignment="Right"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
<Grid x:Name="TariffTariffStepsButtons" Grid.Column="1">
<Grid Height="50">
<Button x:Name="TariffTariffStepAdd" HorizontalAlignment="Center" VerticalAlignment="Top"
Click="TariffTariffStepAdd_Click" Background="Transparent" Style="{StaticResource LessThanButton}">
</Button>
<Button x:Name="TariffTariffStepRemove" HorizontalAlignment="Center" VerticalAlignment="Bottom"
Click="TariffTariffStepRemove_Click" Background="Transparent" Style="{StaticResource GreaterThanButton}">
</Button>
</Grid>
</Grid>
</Grid>
<Grid x:Name="TariffStepsGrid" Grid.Row="1" Grid.Column="1" DataContext="{StaticResource tariffStepViewSource}">
<!-- Some controls for properties of the TariffStep and buttons for add / remove a TariffStep -->
<ListBox x:Name="TariffStepList" ItemsSource="{Binding}" HorizontalAlignment="Right" VerticalAlignment="Top"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left" Height="130" Width="200" Margin="0 15 20 5"
SelectionChanged="TariffStep_SelectionChanged" GotFocus="TariffStepList_GotFocus" TabIndex="22">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="2 2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=DurationV, Mode=TwoWay}" Grid.Column="0" Width="60" TextAlignment="Left"/>
<TextBlock Text="{Binding Path=PeriodV, Mode=TwoWay}" Grid.Column="1" Width="60" TextAlignment="Center"/>
<TextBlock Text="{Binding Path=CostV, Mode=TwoWay}" Grid.Column="2" Width="60" TextAlignment="Right"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
<Grid x:Name="TariffActionGrid" Grid.Row="1" Grid.Column="0"><!-- Buttons for save, etc. --> </Grid>
<Grid x:Name="AllTariffsGrid" Grid.Row="2" Grid.Column="0" VerticalAlignment="Top" Grid.ColumnSpan="2">
<DataGrid x:Name="ListTarif1" HorizontalAlignment="Right" Height="255" VerticalAlignment="Top" AutoGenerateColumns="False"
ItemsSource="{Binding}" Width="760" Margin="20,25,20,0" SelectionChanged="ListTarif1_SelectionChanged"
CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="DescripciĆ³n" Binding="{Binding DescriptionV, Mode=TwoWay}" IsReadOnly="True" Width="152"/>
<DataGridTextColumn Header="Fecha de Inicio" Binding="{Binding StartDateV}" IsReadOnly="True" Width="152"/>
<DataGridTextColumn Header="Fecha Final" Binding="{Binding EndDateV}" IsReadOnly="True" Width="152"/>
<DataGridTextColumn Binding="{Binding CurrencyV.Code}" Header="Moneda" IsReadOnly="True" Width="152"/>
<DataGridTextColumn Binding="{Binding InitialCostV}" IsReadOnly="True" Width="152">
<DataGridTextColumn.Header>
<AccessText TextWrapping="WrapWithOverflow" Width="100" TextAlignment="Center">Costo Inicial</AccessText>
</DataGridTextColumn.Header>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</TabItem>
For populating the TariffStepList listbox (the one for the collection of all tariffs) in code behind was implemented a filter that allowed in the view of the tariffStepViewSource only the tariffsteps that were not already assigned to the tariff:
public void TariffStepsNonInTariffFilter(object sender, FilterEventArgs e)
{
TariffStep tariffStep = e.Item as TariffStep;
var Tariff = ListTarif1.SelectedItem as Tariff;
if (Tariff != null)
{
if (tariffStep.Tariffs.Contains(Tariff))
{
e.Accepted = false;
return;
}
}
e.Accepted = true;
}
That filter was assigned to the tariffStepViewSource only when the app has the Tariff tab on focus, when the focus were to another tab, it was unasigned.
Well, all that worked like a charm, but in the new design there was no need for the tariffStepViewSource because the tariffSteps were assigned directly to the tariff (it didn't matter that they were repeated in the database). As can be seen in the following xaml, the binding is to the collection of tariffSteps of the tariff ( DataContext="{Binding Path=TariffSteps} ).
<TabItem Name="Tariff_Tab" HorizontalAlignment="Left" TabIndex="5" Header="Tarifas" Style="{StaticResource HorizontalTab}">
<Grid x:Name="TariffsGrid" DataContext="{Binding Source={StaticResource tariffViewSource}}">
<Grid x:Name="TariffDetailGrid" Grid.Row="0" Grid.Column="0" DataContext="{Binding}">
<!-- grids & controls for properties of the Tariff & the Currency entity -->
<Grid x:Name="TariffTariffStepsGrid" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right"
DataContext="{Binding Path=TariffSteps}">
<TextBox x:Name="TariffStepCost" HorizontalAlignment="Right" VerticalAlignment="Top" VerticalContentAlignment="Center"
HorizontalContentAlignment="Right" Margin="0,115,225,0" Height="25" Width="100"
Text="{Binding Path=CostV, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, StringFormat=N2}"
LostFocus="TariffStepCost_LostFocus" TabIndex="21"
IsEnabled="{Binding DataContext.Source.Count, Converter={StaticResource IsEnabledBySourceCountConverter},
RelativeSource={RelativeSource Self}}"/>
<Label x:Name="TariffStepCostlabel" Height="25" Content="Costo:" Margin="0,115,325,0" VerticalAlignment="Top"
VerticalContentAlignment="Center" HorizontalAlignment="Right" HorizontalContentAlignment="Left" Width="55" Padding="0"/>
<!-- Some more controls for other properties of the TariffStep and buttons for add / remove a TariffStep -->
<ListBox x:Name="TariffStepList1" ItemsSource="{Binding Path=TariffSteps}" HorizontalAlignment="Right" VerticalAlignment="Top"
VerticalContentAlignment="Center" HorizontalContentAlignment="Left" Height="130" Width="200" Margin="0 15 20 5"
TabIndex="22">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="2 2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=DurationV, Mode=TwoWay}" Grid.Column="0" Width="60" TextAlignment="Left"/>
<TextBlock Text="{Binding Path=PeriodV, Mode=TwoWay}" Grid.Column="1" Width="60" TextAlignment="Center"/>
<TextBlock Text="{Binding Path=CostV, Mode=TwoWay}" Grid.Column="2" Width="60" TextAlignment="Right"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
<!-- TariffActionGrid && AllTariffsGrid -->
</Grid>
</TabItem>
The fact is that, no matter what I do, if I remove the filter from code behind, in the listbox "TariffStepList1" nothing get shown. I can add new tariffSteps and save the context, but when I close the app and open it again, nothing is shown. I've tested all option, even creating new ListBox, button, etc. in a different tab. I have checked that there is no remaining references to tariffStepViewSource in the whole project, still there is no way the tariffSteps get shown.
In another tab I have the same xaml controls structure in which a navigation property is modified with exactly the same master - detail scenario (an entity named Extension which have a collection of associated email addresses), and there is no problem there. As soon as I re-incorporate the tariffStepViewSource, with it corresponding filter, the tariffSteps get shown, even when there binding in the Grid is not to the viewsource.

WPF TextBox not trimming in DataTemplate

I have an odd problem with TextBox with TextTrimming set to CharacterElipsis used in a DataTemplate in WPF application. At the start of application everything works fine. But when I am resizing the window - reducing the width, the trimming is not working.
In an example below:
<Grid>
<DockPanel>
<DockPanel.Resources>
<DataTemplate x:Key="lowerLevel" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="34*" />
<ColumnDefinition Width="26*" />
<ColumnDefinition Width="26*" />
<ColumnDefinition Width="14*" />
</Grid.ColumnDefinitions>
<TextBlock Text="textboxvalue1" Grid.Column="0" FontWeight="Bold" VerticalAlignment="Center" Margin="15,10,0,10" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" />
<TextBlock Text="textboxvalue2" Grid.Column="1" FontWeight="Bold" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" />
<TextBlock Text="textboxvalue3" Grid.Column="2" FontWeight="Bold" VerticalAlignment="Center" Margin="0,10,0,10" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" />
<CheckBox IsChecked="True" Content="ApprovedText" FontWeight="Bold" Grid.Column="3" VerticalAlignment="Center" Margin="0,10,15,10" />
</Grid>
</DataTemplate>
</DockPanel.Resources>
<ListView x:Name="listViewControl" ItemTemplate="{StaticResource lowerLevel}" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" />
</DockPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="34*" />
<ColumnDefinition Width="26*" />
<ColumnDefinition Width="26*" />
<ColumnDefinition Width="14*" />
</Grid.ColumnDefinitions>
<TextBlock Text="textboxvalue1" Grid.Column="0" FontWeight="Bold" VerticalAlignment="Center" Margin="15,10,0,10" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" />
<TextBlock Text="textboxvalue2" Grid.Column="1" FontWeight="Bold" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" />
<TextBlock Text="textboxvalue3" Grid.Column="2" FontWeight="Bold" VerticalAlignment="Center" Margin="0,10,0,10" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" />
<CheckBox IsChecked="True" Content="ApprovedText" FontWeight="Bold" Grid.Column="3" VerticalAlignment="Center" Margin="0,10,15,10" />
</Grid>
</Grid>
I am having two identical Grids, but first one is placed in a DataTemplate and the second is just a separate control. TextBoxes in bottom grid are trimming correctly, when resizing window, however the TextBoxes from DataTemplate do not fit the width of parent columns while window resizing.
The code behind is:
public partial class MainWindow : Window
{
private ListCollectionView comparedFamiliesView;
public ListCollectionView ComparedFamiliesView
{
get
{
if (comparedFamiliesView == null)
{
comparedFamiliesView = new ListCollectionView(new List<Object>() { new Object(), new Object(), new Object() });
}
return comparedFamiliesView;
}
}
public MainWindow()
{
InitializeComponent();
listViewControl.ItemsSource = ComparedFamiliesView;
}
}
It basically adds three objects to have something to view on ListView.
I was trying different combinations of VerticalAlignment, VerticalContentAlignment - didn't work.
What I have tried was to place each TextBox in separate Grid in order to bind its Width to TextBox Width or MaxWidth, like:
<Grid Grid.Column="0" x:Name="grid1">
<TextBlock Text="textboxvalue1" FontWeight="Bold" VerticalAlignment="Center" Margin="15,10,0,10" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" MaxWidth="{Binding ActualWidth, ElementName=grid1}" />
</Grid>
Didn't work either.
How can I force TextBoxes in DataTemplate to behave the same way as those in separate Grid?
Or what am I doing wrong with TextTrimming when using in DataTemplate.
Thank you for your help!!!
Regards,
Ariel
Try to set the ScrollViewer.HorizontalScrollBarVisibility attached property of the ListView to Disabled:
<ListView x:Name="listViewControl" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ...

Formatting of text in a textblock in windows phone 7

I am have a text which is has bold, underline and italic html characters. For example
<b> hello<b> how are <i>you</i>. I am <u>fine</u>
I have to show it in formatted form in a textblock on WP7. I have a listbox like this
<ListBox x:Name="LBayaDetail" Loaded="LBayaDetail_Loaded" Margin="6,0,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="ayaContent" Margin="0,6,0,0" Hold="ayaContent_Hold" Tap="ayaContent_Tap" Loaded="ayaContent_Loaded" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="6"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="6" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Background="#FFC5AC88" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="ayaIndex" Text="{Binding aya}" FontSize="36" Margin="0" FontWeight="Bold" HorizontalAlignment="Center" />
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Center">
<Image Source="{Binding BookmarkImage}" HorizontalAlignment="Center" Width="48" Height="48" Margin="0,0,0,12" />
<Image Source="{Binding NoteImage}" HorizontalAlignment="Center" Width="48" Height="48" Margin="0,0,0,12" />
<Image Source="{Binding TagImage}" HorizontalAlignment="Center" Width="48" Height="48" Margin="0,0,0,12" />
</StackPanel>
</Grid>
<Grid Grid.Row="1" Background="#FFC5AC88" x:Name="Media" Tap="Media_Tap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Source="/Images/Media-Play(1).png" Width="30" Height="30" HorizontalAlignment="Center" Margin="12,0,0,0" VerticalAlignment="Top" />
</Grid>
<!--ini pak dimana tempat untuk ayat dan translasi-->
<Grid Grid.Column="2" Background="#FFAC9574" Margin="6,0,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="aya" TextWrapping="Wrap" Text="{Binding text}" HorizontalAlignment="Right" FontFamily="/Fonts/me_quran2.ttf#me_quran2" FontSize="{Binding FontSizeAya}" Foreground="Black" Margin="24,0,12,-12" TextAlignment="Right" Visibility="{Binding visibility1}" />
</Grid>
<Grid Grid.Column="2" Grid.Row="1" Margin="6,0,0,0" Background="#FFAC9574" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel>
<TextBlock Visibility="{Binding visibility2}" x:Name="translation" Text="{Binding translation}" TextWrapping="Wrap" HorizontalAlignment="Right" FontFamily="/Fonts/ARIALUNI.TTF#Arial Unicode MS" FontSize="{Binding FontSizeTranslation}" Foreground="#FF5D2A07" Margin="12,6,6,0" />
<TextBlock Visibility="{Binding visibility3}" x:Name="translation2" Text="{Binding translation2}" TextWrapping="Wrap" HorizontalAlignment="Right" FontFamily="/Fonts/ARIALUNI.TTF#Arial Unicode MS" FontSize="{Binding FontSizeTranslation}" Foreground="DarkGreen" Margin="12,20,6,0" />
</StackPanel>
</Grid>
<!-- -->
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I fetch from database like
App.Listxyz = (Application.Current as App).db.SelectList<Aya>(strSelect);
And assign it to Listbox like this
LBayaDetail.ItemsSource = App.ListAyaBySurah;
And shows the text as it is and do not format it which is obvious. I searched for it and I was able to format individual textblock by using "RUN" but I am unable to do it in listbox.
I also tried to use HTMLTextBlock but it also doesn't format the text and shows it like this
Hi
How
Are
You
Any help will be much appreciated that how do I format a textblock with different text decorations.
Thanks
You should place a grid and a stackpanel inside the listbox. Something like the following
<Grid>
<StackPanel Grid.Column="1">
<TextBlock Padding="0,5,0,2" TextWrapping="Wrap">
<Run Text="{Binding test}" FontWeight="Bold" /> <Run Text="{Binding test2}" />
<LineBreak/>
<Run Text="{Binding test3}" />
</TextBlock>
</StackPanel>
</Grid>
One way to do that is:
public class FormattedText
{
public string Text { get; set; }
public bool IsBold { get; set; }
public bool IsItalic { get; set; }
public bool IsUnderlined { get; set; }
}
Have a method that converts the HTML you stored in your db to a list of the class you have above
example:
From this:
<b> hello<b> how are <i>you</i>. I am <u>fine</u>
to this:
First element:
Text = "hello"
IsBold = true
skip what not needed since bool default value is false
Second element
Text =" how are"
skip what not needed since bool default value is false
Third item
Text ="you"
IsItalic=true;
skip what not needed since bool default value is false
and so on....
and then have another method that from that list creates a list of Runs to be added to your TextBlock or
maybe create a custom TextBlock witch take the List<FormattedText> from DataContext and process it by adding the Run elements to self

AvalonDock 2.2 - Full width TitleTemplate (fill parent container)

Hy everyone!
I created a title template in AvalonDock 2.2 (WPF Toolkit). The problem is that the context menu of the LayoutAnchorable is only triggered when I right-click on the part of the title that contains something (and not the entire width of the anchorable).
Here is the relevant code segment I'm using now:
<ad:DockingManager x:Class="Pdn.Gui.Docking.Control.DockingSystem" ...
AnchorablesSource="{Binding Path=Panels}">
<ad:DockingManager.Resources>
<DataTemplate x:Key="DockingWindowTitleDataTemplate" DataType="{x:Type ad:LayoutContent}">
<StackPanel ToolTip="{Binding Path=Content.ToolTip}" Orientation="Horizontal" HorizontalAlignment="Stretch">
<Image MaxHeight="16" MaxWidth="16" VerticalAlignment="Center"
Source="{Binding Path=Content.IconSource, Converter={StaticResource IconToImageSourceConverter}}" />
<TextBlock Text="{Binding Path=Content.Name}" Margin="5,0,0,0" VerticalAlignment="Center"/>
<TextBlock Text="*" Visibility="{Binding Path=Content.DirtySignVisibility}" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DockingWindowTitleGridDataTemplate" DataType="{x:Type ad:LayoutContent}">
<Grid ToolTip="{Binding Path=Content.ToolTip}" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" MaxHeight="16" MaxWidth="16" VerticalAlignment="Center"
Source="{Binding Path=Content.IconSource, Converter={StaticResource IconToImageSourceConverter}}" />
<TextBlock Grid.Column="1" Text="{Binding Path=Content.Name}" Margin="5,0,0,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="*" Visibility="{Binding Path=Content.DirtySignVisibility}" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="DefaultPanelTitle">
<TextBlock Text="{Binding Path=Content.Name}" TextTrimming="CharacterEllipsis" />
</DataTemplate>
...
</ad:DockingManager.Resources>
<ad:DockingManager.AnchorableTitleTemplate>
<StaticResource ResourceKey="DockingWindowTitleDataTemplate" />
</ad:DockingManager.AnchorableTitleTemplate>
...
</ad:DockingManager>
When I use the DefaultPanelTitle template (which is the default template of the theme) everything is fine, the context menu is triggered on the full width of the title part.
However when I use the other two templates (Image-Name-IsDirty elements), the context menu is triggered only on the beginning of the title area (and not right to the asterix).
I'm guessing I should tell the container to fill its parent container, but I can't figure out how. I used StackPanel, Grid, DockPanel (LastChildFill = "True") with HorizontalAlignment set to Stretch. What kind of container should I use?
What am I missing?
P.S.: I can only respond to your answers for another 12 hours, then I'm gone for a while (week). But I'm not abandoning this question until it's answered :) Thanks for your patience.
Well, the solution was quite simple. I wrapped the StackPanel in a Label. Now the context menu can be triggered on every pixel in the title part. The template now looks like this:
<ad:DockingManager x:Class="Pdn.Gui.Docking.Control.DockingSystem" ...
AnchorablesSource="{Binding Path=Panels}">
<ad:DockingManager.Resources>
<DataTemplate x:Key="DockingWindowTitleDataTemplate" DataType="{x:Type ad:LayoutContent}">
<Label>
<StackPanel ToolTip="{Binding Path=Content.ToolTip}" Orientation="Horizontal" HorizontalAlignment="Stretch">
<Image MaxHeight="16" MaxWidth="16" VerticalAlignment="Center"
Source="{Binding Path=Content.IconSource, Converter={StaticResource IconToImageSourceConverter}}" />
<TextBlock Text="{Binding Path=Content.Name}" Margin="5,0,0,0" VerticalAlignment="Center"/>
<TextBlock Text="*" Visibility="{Binding Path=Content.DirtySignVisibility}" VerticalAlignment="Center"/>
</StackPanel>
</Label>
</DataTemplate>
...
</ad:DockingManager.Resources>
<ad:DockingManager.AnchorableTitleTemplate>
<StaticResource ResourceKey="DockingWindowTitleDataTemplate" />
</ad:DockingManager.AnchorableTitleTemplate>
...
</ad:DockingManager>
I love simple solutions.

How to change GridView.ItemTemplate while app is running?

In my app I have page with GridView and ComboBox. I want to change GridView.ItemTemplate property according to selected item in ComboBox. How should I implement it?
btw, I know about this question, but it is quite old and it does not look like "best practice". (How visibility/invisibility of ui control affects cpu/gpu load?)
My GridView:
<GridView x:Name="gridViewMain" Grid.Row="1" SelectionMode="None" IsItemClickEnabled="True"
ItemsSource="{Binding CurrentList}" ItemTemplate="{StaticResource gridViewMainItemTemplate}"
Loaded="gridViewMain_Loaded" LayoutUpdated="gridViewMain_LayoutUpdated">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ItemClick">
<core:CallMethodAction MethodName="GridViewClick"
TargetObject="{Binding Mode=OneWay}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</GridView>
One of my templates:
<DataTemplate x:Key="gridViewMainItemTemplate">
<Grid x:Name="gridATemplate" Width="185" Height="288">
<Image x:Name="imgATemplate" Source="{Binding image_url}" Stretch="UniformToFill"
HorizontalAlignment="Center" VerticalAlignment="Center" />
<Grid Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}" VerticalAlignment="Bottom">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlockTitle" Text="{Binding title}"
TextWrapping="Wrap" Style="{StaticResource BodyTextBlockStyle}" Margin="5,0,0,0"
Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Foreground="White" FontWeight="Bold"
MaxHeight="50" />
<TextBlock x:Name="textBlockType" TextWrapping="Wrap" Style="{StaticResource BodyTextBlockStyle}"
Margin="5,0,0,0"
Grid.Column="0" Grid.Row="1" Foreground="White" Text="{Binding type}" FontWeight="Bold" />
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
<TextBlock x:Name="textBlockProgressL" TextWrapping="Wrap"
Style="{StaticResource BodyTextBlockStyle}" FontWeight="Bold" Foreground="White"
Text="Progress:" />
<TextBlock x:Name="textBlockProgressV" TextWrapping="Wrap"
Style="{StaticResource BodyTextBlockStyle}" FontWeight="Bold" Foreground="White"
Text="{Binding watched_episodes}" Margin="10,0,0,10" />
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
Sure you can do this! In XAML you can do anything. What you cannot do is change the Template on the fly without re-rendering. Remember, this is like telling your printer to use card stock. It will obey. If you change the setting to use notebook paper, it will obey that, too. You will just have to print again since it has already printed on card stock.
There are a few ways for you to re-render a GridView. One way is to navigate away from the page and navigate back. That's not ideal sounding in your scenario. Odds are, in your scenario, you just need to reset the ObservableCollection you are using. Like this:
void Reset<T>(ObservableCollection<T> collection)
{
var original = collection.ToArray();
collection.Clear();
foreach (var item in original)
collection.Add(item);
}
Best of luck!
You'll want to use datatemplateselector
http://blogs.msdn.com/b/bryanbolling/archive/2012/12/08/how-to-control-the-datatemplateselector-in-windows-store-apps.aspx
You can create multiple itemtemplates and choose which one to display based on any condition.
You'll have to refresh the gridview whenever the selection changes.

Categories