Set a default name to a combobox in WPF - c#

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" />

Related

How to modify Image Source in WPF XAML dynamically

I have a WPF App that has (so far) 2 modes of display, regularmode and widgetmode.
I am using Prism 6 with MVVM design pattern.
MainWindowViewModel knows the mode of display.
ToolBarView has, as expected, a toolbar of buttons and the buttons shall be dynamically changed to different images depending on the mode of the view. If the mode is WidgetMode, it switches to the image with an identical name but with an '_w' added. So instead of "image.png", it's "image_w.png".
What I'd like to do is create a string in ToolBarView that is updated to either String.Empty or to "_w", depending on the mode. I'd also like the image root folder to be a global string, rather than a hardcoded string, so I have defined that in app.xaml.
<Application.Resources>
<sys:String x:Key="ImageURIRoot">/MyApp;component/media/images/</sys:String>
</Application.Resources>
Then in my toolbarview (a usercontrol), I did this:
<UserControl.Resources>
<converters:StringToSourceConverter x:Key="strToSrcConvert"/>
<sys:String x:Key="BtnImgSuffix">_w</sys:String>
.
.
.
</UserControl.Resources>
Note that the string is hardcoded; eventually, I will change it dynamically based off the windowmode.
I then put the Buttons in a Listbox
<ListBoxItem Style="{StaticResource MainButton_Container}">
<Button Command="{Binding ButtonActionDelegateCommand}" Style="{StaticResource Main_Button}">
<Image Source="{Binding Source={StaticResource ImageURIRoot}, Converter={StaticResource strToSrcConvert}, ConverterParameter='{}{0}button.png'}" />
</Button>
</ListBoxItem>
Converter code:
public class StringToSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter is string)
{
return string.Format(parameter.ToString(), value);
}
return null;
}
public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
So that works. But what I want is to have the ConverterParameter equal "{}{0}button{1}.png", where {0} is the URI Root and {1} is the suffix. But I can't figure out how to do it. I know it's simple, but I can't put my finger on it!
Please help!
Figured it out and it was through multibinding. The way I did it was create a converter that inherits from IMultiValueConverter. Its "Convert" method looks like this:
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
ImageSourceConverter conv = new ImageSourceConverter();
int suffixPos = ((String)parameter).Length - 4;
var returnValue = ((String)parameter).Insert(suffixPos, values[1].ToString());
returnValue = Path.Combine(values[0].ToString(), returnValue);
ImageSource imgsrc = conv.ConvertFromString(returnValue) as ImageSource;
return imgsrc;
}
The xaml looks like this:
<Image Height="30" Width="40" diag:PresentationTraceSources.TraceLevel="High">
<Image.Source>
<MultiBinding Converter="{StaticResource stringsToSrcConvert}" ConverterParameter="buttonImg.png">
<Binding Source="{StaticResource ImageURIRoot}"/>
<Binding Source="{StaticResource BtnImgSuffix}"/>
</MultiBinding>
</Image.Source>
</Image>
Also, had to modify the URIRoot
<Application.Resources>
<sys:String x:Key="ImageURIRoot">pack://application:,,,/MyApp;component/media/images/</sys:String>
</Application.Resources>
Thanks, Clemens!

Getting Control of RadioButton WPF

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.

WPF create object using IValueConverter with binding object's properties

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.

How to make IValueConverter return text with different fontsizes, superscripts and/or subscripts

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>

Two-way binding requires path or xpath

I want to increase Progress-bar value based on two textbox's Text. I wrote this XAML but there is an error "Two-way binding requires path or xpath" when I do MultiBinding in ProgressBar.Value
<Window.Resources>
<local:Class1 x:Key="ConverterM"/>
</Window.Resources>
<TextBox Height="23" HorizontalAlignment="Left" Margin="157,59,0,0"
Name="textBox1" VerticalAlignment="Top" Width="120" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="157,108,0,0"
Name="textBox2" VerticalAlignment="Top" Width="120" />
<ProgressBar Height="24" HorizontalAlignment="Left" Margin="120,160,0,0"
Name="progressBar1" VerticalAlignment="Top" Width="243" >
<ProgressBar.Value>
<MultiBinding Converter="{StaticResource ConverterM}">
<Binding />
<Binding ElementName="textBox1" Path="Text" />
<Binding ElementName="textBox2" Path="Text" />
</MultiBinding>
</ProgressBar.Value>
</ProgressBar>
Value Converter:
public class Class1 : IMultiValueConverter
{
public object Convert(object[] values,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture)
{
if (values[1] != null && values[2]!=null)
{
if (((string)values[1]).Length==((string)values[2]).Length)
{
return 5.0;
}
}
else
{
return 0.0;
}
}
public object[] ConvertBack(object value,
Type[] targetTypes,
object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I think that <Binding /> is not necessary. try to delete it and change indexes in converter.
Two-way binding requires path or xpath
This happens when you haven’t set the Path= on binding. By default WPF binding will take the Path= part by default.
To avoid this you need to give Path for each Binding you specify in MultiBinding. here in your case there was an empty binding which has no Path defined thats why you have experience with the above error.
I have came across the same issue but the accepted answer does not say what the error is, So thought of sharing this.

Categories

Resources