Here what i have in xaml:
<DataGrid Name="dataGrid">
<DataGridTemplateColumn Header = "Base" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0" GroupName="{Binding Index}" Name="ABCD" Content="ABCD" IsChecked="True" Checked="radioButton_Checked"/>
<RadioButton Grid.Column="1" GroupName="{Binding Index}" Name="XYZ" Content="XYZ" Checked="radioButton_Checked" />
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid>
Here are some codes in some function (any) xaml.cs:
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i);
FrameworkElement radioButton = dataGrid.Columns[0].GetCellContent(row) as FrameworkElement;
radioButton.Visibility = Visibility.Hidden;
I can hide the visibility as I am hiding whole cell. but i want to change a radio button content in runtime from "XYZ" to "HAHAHA". How can i achieve this?
You might be able to use a value converter to achieve this. This can be used to change the name based on the index value;
public class IndexToXYZOrHaHaHaConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var index = (int) value;
if (index > 10)
{
return "XYZ";
}
return "HaHaHa";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You'll need to create an instance of the class by adding a static resource to your resource dictionary.
<local:IndexToXYZOrHaHaHaConverter x:Key="IndexToXYZOrHaHaHaConverter"/>
You'll then need to change the content of the radio button from "xyz" to this;
Content="{Binding Index, Converter={StaticResource IndexToXYZOrHaHaHaConverter}}"
This should dynamically switch the value between xyz and HaHaHa depending on the index. In the example I gave this depends on whether the value is greater or less than 10, which is probably not what you want so you'll have to fix the logic. I've also assumed that index is an integer, you may need to change that too if index is something else.
Converters are great for setting properties based on bound values that don't directly correspond to the value they are bound to e.g. converting a string to a color.
Hope this is of some help.
Related
my objects which I use to binding in XAML can have only string properties. But in binding I need other type. I thought that I use Converter function from IValueConverter, where I'll create object from string properties and return this. One property which is a string will be empty, and in binding I'll return other object from Converter method. I tried this but in Convert method my main object from ObservableCollection is null. This's a piece of my XAML
<Maps:MapItemsControl ItemsSource="{Binding}">
<Maps:MapItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="Transparent" Tapped="ItemStckPanel">
<Image Source="/Assets/pushpin.gif" Height="30" Width="30"
Maps:MapControl.Location="{Binding Location,
Converter={StaticResource StringToGeopoint}}"
Maps:MapControl.NormalizedAnchorPoint="0.5,0.5"/>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5">
<TextBlock FontSize="20" Foreground="Black" Text="{Binding Name}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</Maps:MapItemsControl.ItemTemplate>
</Maps:MapItemsControl>
And this's my Convert method:
public object Convert(object value, Type targetType, object parameter, string language)
{
Event _event = (Event) parameter;
BasicGeoposition position = new BasicGeoposition();
position.Latitude = _event.Latitude;
position.Longitude = _event.Longitude;
return new Geopoint(position);
}
I want to pass the my actual parent object in Converter method. Solution is change
Maps:MapControl.Location="{Binding Location,
Converter={StaticResource StringToGeopoint}}"
to
Maps:MapControl.Location="{Binding Converter={StaticResource StringToGeopoint}}"
It works :)
The bound object is fed into the "value" parameter of the Convert()-Method.
You're accessing the parameter which corresponds to
<... ConverterParameter= .../>
which isn't set in your xaml.
You would actually have to write your Convert()-Method like this:
public object Convert(object value, Type targetType, object parameter, string language)
{
Event _event = (Event) value;
BasicGeoposition position = new BasicGeoposition();
position.Latitude = _event.Latitude;
position.Longitude = _event.Longitude;
return new Geopoint(position);
}
/UPDATE:
The ItemsSource={Binding} on your Maps:MapItemControl binds to the DataContext of the parent object. This should be your ObservableCollection.
Within the ItemTemplate your Image has a "Location"-Property that is bound to the "Location"-property of each item within your ObservableCollection. You could also write:
{Binding Path=Location, Converter={StaticResource StringToGeopoint}}
Now before that binding is fully evaluated, the Object that is stored in the Location-property is passed to the converter and the result is then handed to the "Location"-Property on the Image.
If you are getting null objects to be passed to the "value"-parameter, that means that the original Binding hands null values to the Converter either because the Property on the source object is null or because the property doesn't exist.
I have a textblock in my listbox called "feedTitle" which I want to change the forground color of. I use Foreground="{Binding Converter={StaticResource NewsTextColorConverter}}" for the binding of the forground color. Now the strange problem is that, if I choose a color in the listpicker("Lys" or "Dark" value) it runs the IValueConverter Convert method, but it dont show the color in the GUI, only if I restart my whole app it shows the color I chosen. It's like it only set the color of the forground of the textblock once.
MainPage.xaml
<ListBox Grid.Row="1" Name="feedListBox" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectionChanged="feedListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Top">
<TextBlock TextDecorations="Underline" FontSize="24" Name="feedTitle" TextWrapping="Wrap" Margin="12,0,0,0" Foreground="{Binding Converter={StaticResource NewsTextColorConverter}}" Text="{Binding Title.Text, Converter={StaticResource RssTextTrimmer}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And in my app file:
App.xaml
<Application.Resources>
<converter:NewsTextColorConverter xmlns:converter="clr-namespace:NordjyskeRss" x:Key="NewsTextColorConverter" />
</Application.Resources>
I use a listpicker where a user select the value "Mørk" or "Lys" and then I want the textblock forground color to update its forground color. I call the Convert method and pass null as arguments, it seems to run the method fine:
MainPage.cs
private void lpkThemes_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Make sure we don't handle the event during initiation.
if (e.RemovedItems != null && e.RemovedItems.Count > 0)
{
if (this.lpkThemes.SelectedItem != null)
{
settings[THEMES_SETTING_KEY] = lpkThemes.SelectedItem.ToString();
if (lpkThemes.SelectedItem.ToString() == "Mørk")
{
n.Convert(null, null, null, null);
}
else
{
n.Convert(null, null, null, null);
}
}
}
}
This is where I use a IValueConverter to check for what color to use on the textblock and then add it:
MainPage.cs
public class NewsTextColorConverter : IValueConverter
{
protected IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
protected const string THEMES_SETTING_KEY = "Themes";
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (settings.Contains(THEMES_SETTING_KEY))
{
string themesValue = (string)settings[THEMES_SETTING_KEY];
if (themesValue == "Mørk")
{
return new SolidColorBrush(Colors.Green);
}
else
{
return new SolidColorBrush(Colors.Blue);
}
}
return new SolidColorBrush(Colors.Green);
//throw new NotSupportedException("ColorToBurshConverter only supports converting from Color and String");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I think you need to redesign your app in the following way:
Add the following line into your app.xaml or page resources: <SolidColorBrush x:Key="brushListItemsForeground" Color="#FFFFFFFF" />
Replace Foreground="{Binding Converter={StaticResource NewsTextColorConverter}}" with Foreground="{StaticResource brushListItemsForeground}"
In your SelectionChanged:
var brush = (SolidColorBrush)Application.Current.Resources["brushListItemsForeground"]; if you’ve added the brush to app.xaml, or = (SolidColorBrush)this.Resources["brushListItemsForeground"]; if you’ve added the brush to page resources. Then change the Color property of the brush based on your settings.
P.S. There’re also other correct ways: e.g. create a SettingsContainer class that implements INotifyPropertyChanged, add it into some resource dictionary <local:SettingsContainer x:Key="mySettings" />, then bind to its properties e.g. Foreground="{Binding listItemsForeground, Source={StaticResource mySettings}}", when you need to change the value, change the listItemsForeground property of your class and raise PropertyChanged.
Currently, you’re abusing value converter using then as value providers, they were not designed for that, and that is why you have issues updating those values.
Can anyone please let me know how I could make a Converter return text with varying font-sizes, so that the bound textblock can display it? If this is not possible with a TextBlock, I can use alternative element as well.
Here is the code that I have right now, this obviously doesn't work
In my XAML file:
<TextBlock Text="{Binding Converter={StaticResource LabelFormatConerter}}"/>
In my XAML.cs file:
public class LabelFormatConerter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
TextBlock tb = new TextBlock();
Run runLargeFont = new Run();
runLargeFont.FontSize = 18;
runLargeFont.Text = "Larger Font Text";
tb.Inlines.Add(runBase);
Run runSmallFont = new Run();
runSmallFont.FontSize = 8;
runSmallFont.BaselineAlignment = BaselineAlignment.Superscript;
runSmallFont.Text = "Smaller Font Text";
tb.Inlines.Add(runSmallFont);
return tb.Text;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
This should work for you:
<TextBlock FontFamily="Calibri">
<Run>Normal Text</Run>
<Run Typography.Variants="Superscript">Test</Run>
<Run Typography.Variants="Subscript">7</Run>
</TextBlock>
Not all fonts support super\subscripts, so I had to specify it explictly.
What will be your input? Two/three separate values, or one value that you need to split into a normal value, superscript and subscript?
This might be possible to do with a TextBlock but I don't know how. Your converter returns a collection of Run objects, while the Text property expects a string.
An alternative is to user an items control:
<ItemsControl ItemsSource="{Binding Converter={StaticResource LabelFormatConerter}}" />
and return
tb.Inlines
from your converter. (ideally you just create just a collection inside your converter, not a new TextBlock)
A converter is not the right tool for this job - this is what ContentTemplate is there for. Simply use a ContentControl, bind the data to the Content property and display the data however your want to in your ContentTemplate:
<ContentControl Content="{Binding Person}">
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBlock>
<Run FontSize="18" Text="{Binding FirstName}" />
<Run FontSize="8" Text="{Binding LastName}" />
</TextBlock>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
So I am having a problem with my column updating, as far as I can see it's updating fine but for some reason the actual checkboxes that should be getting checked aren't. I can't seem to figure out why as all the values are set as true.
using (IDbConnection connection = sessionFactory.ConnectionProvider.GetConnection())
{
if (TableExists(connection, "tbl_ecom_cat_feature") &&
ColumnExists(connection, "tbl_ecom_cat_feature", "display_on_search"))
{
using (IDbCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "UPDATE tbl_ecom_cat_feature SET display_on_search = 1";
cmd.ExecuteNonQuery();
}
}
EDIT: I have just realised that in my Checkbox_Check method I haven't actually put anything in to check if it's checked... I'm actually unsure how I would grab the data from the SQL column to see if it's true and if it is, return the box as checked.
Code in which I display the checkboxes:
public class StringToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value is string)
{
var input = (string)value;
if (string.IsNullOrEmpty("Name"))
{
return Visibility.Collapsed;
}
else
{
return Visibility.Visible;
}
}
return Visibility.Visible;
}
and the WPF code in which these checkboxes are displayed is as follows:
<GridViewColumn Header="Display On Search">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Visibility="{Binding StringToVisibilityConverter}" IsChecked="{Binding StringToVisibilityConverter}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
You need to bind your properties to a value from your datacontext and then assign the converter in the binding, so it will convert your source value, to a target value. Code:
<GridViewColumn Header="Display On Search">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Visibility="{Binding sourceProp, Converter={StaticResource myStringToVisibilityConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
and your will need to specify your converter as a resource like:
<Window.Resources>
<con:StringToVisibilityConverter x:Key="myStringToVisibilityConverter" />
</Window.Resources>
the resource could also be set on another level in the XAML eg. the gridview.
I have a combobox filled with int's representing years. The years I have add them to an ObservableCollection, but my problem is when I load the project the combobox its blank by default. I want to set a default name to it, like "Years", but I don't want solution like set the isEditable to true, or inserting a string at the beginning. I want a pure xaml solution if it is posible.
This is my current xaml file:
<RSControls:SmoothScrollComboBox Grid.Column="1" x:Name="compilationYearCombo" Margin="7,2.04,0,2.04"
SelectedValue="{Binding Path=SelectedYear}"
SelectedValuePath=""
ItemsSource="{Binding Years}"
DisplayMemberPath="" SelectionChanged="compilationYearCombo_SelectionChanged" IsSynchronizedWithCurrentItem="True" Grid.ColumnSpan="2" IsEditable="False" SelectedIndex="0" IsReadOnly="False" Text="Years">
</RSControls:SmoothScrollComboBox>
I tried adding a <TextBlock Text="Years" /> , but that only changed all the elements in the combo to "Years".
I apreciatte a detail explenation how to this, I am just a beginner with WPF.
Thanks.
You can add a visibility converter to your TextBlock
<TextBlock
Visibility="{Binding SelectedItem, ElementName=compilationYearCombo, Converter={StaticResource NullToVisibilityConverter}}"
IsHitTestVisible="False"
Text="Years" />
with this converter:
public class NullToVisibilityConverter : IValueConverter
{
#region Implementation of IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
To show the default text ' -- Select Value --' in Combo Box
<ComboBox Height="23" HorizontalAlignment="Left" Margin="180,18,0,0" Name="cmbExportData" VerticalAlignment="Top" Width="148" ItemsSource="{Binding}" Text="-- Select Value --" AllowDrop="False" IsEditable="True" IsManipulationEnabled="False" IsReadOnly="True" />