I have a grid like this:
<telerik:RadGridView x:Name="DataG"
ItemsSource="{Binding CamposUsu}"
SelectedItem="{Binding Selected}"
CanUserReorderColumns="True"
CanUserResizeColumns="True"
CanUserSortColumns="False"
SelectionUnity="FullRow"
IsReadyOnly="True"
AutoGenerateColumns="False"
Loaded="DataG_Loaded" />
In the .cs file the method DataG_Loaded:
private void DataG_Loaded(object sender, RoutedEventesArgs e)
{
DataTemplate labelTemplate = new DataTemplate();
FrameworkElementFactory label = new FrameworkElementFactory(typeof(Label));
label.SetValue(Label.ContentProperty, "Unlimited");
labelTemplate.VisualTree = label;
labelTemplate.Seal();
this.DataG.Columns[7].CellTemplate = labelTemplate;
//this column 7 is a column called "Vl." with double values
}
Well, when I comment the method DataG_Loaded, my grid is fulfilled correctly with the objects I created on my viewmodel.
When I uncomment the method, the column "Vl." that had values like "93.5", "108.9"... is all fulfilled with the value "Unlimited".
This was already expected.
I want only the cells that the value is > 100.0 to turn to the string "Unlimited". For example:
Is there any way of doing this?
You could use a value converter on your data binding for that column in the XAML instead of using the Loaded event of your grid.
Example
Create a new class that inherits IValueConverter like this:
public class UnlimitedNumberConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (((float)value) > 100)
return "Unlimited";
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
Add a resource to your XAML in order to access the converter:
<converters:UnlimitedNumberConverter x:Key="UnlimitedNumberConverter"/>
where "converters" is a namespace alias declared at the top of your XAML window/user control:
xmlns:converters="clr-namespace:MyApplication.Converters"
Then reference the converter in your data binding on the grid through XAML:
{Binding VI_Value, Converter={StaticResource UnlimitedNumberConverter}}
Related
I've been searching for a solution to display the indexes of items from a ListView for a few hours. I can't add a new property to the data source, as an index property to bind to the value.
I've been trying to Bind to a Converter:
<DataTemplate x:Key="TubeTemplate" x:DataType="data:Tube">
<local:TubeTemplate HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
FavoritesNumber="{Binding Converter={StaticResource IndexConverter}}"
Closed="TubeTemplate_Closed"></local:TubeTemplate>
</DataTemplate>
This is the Converter:
public sealed class IndexConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var item = (ListViewItem)value;
var listView = ItemsControl.ItemsControlFromItemContainer(item) as ListView;
int index = listView.IndexFromContainer(item) + 1;
return index.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
The issue is that my code breaks at: var item = (ListViewItem)value;
The value I'm getting is the DataType binded to each item, instead of the ListViewItem.
What Am I doing wrong?
Use {RelativeSource Mode=TemplatedParent} in the Binding. Then, you can get the ItemContainer with the help of VisualTreeHelper as follows.
<local:TubeTemplate ...
FavoritesNumber="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource IndexConverter}}"
.../>
and
public object Convert(object value, Type targetType, object parameter, string language)
{
var presenter = value as ListViewItemPresenter;
var item = VisualTreeHelper.GetParent(presenter) as ListViewItem;
var listView = ItemsControl.ItemsControlFromItemContainer(item);
int index = listView.IndexFromContainer(item) + 1;
return index.ToString();
}
However, index displayed in this way won't be automatically updated on collection changes. So, if you'll remove some items afterwards, you'd have to implement another function to request each item to reload its index.
Try using
AlternationIndex. Also according to this answer, you should use ListViewItem as RelativeSource
In your case, it would look something like
<DataTemplate>
<TextBlock Text="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource AncestorType=ListViewItem},
StringFormat={}Index is {0}}">
</TextBlock>
</DataTemplate>
Everytime i change my selected item inside my UI it's not updating my combobox.
XAML
<ComboBox x:Name="CompanyComboBox" HorizontalAlignment="Left" Height="26"
Margin="100,41,0,0" VerticalAlignment="Top" Width="144"
SelectionChanged="CompanyComboBox_SelectionChanged"
SelectedItem="{Binding SelectedCompany, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}">
<ComboBox.ItemTemplate>
<DataTemplate>
<ContentPresenter
Content="{Binding Converter={StaticResource DescriptionConverter}}">
</ContentPresenter>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
C#
private Company _selectedCompany;
public Company SelectedCompany
{
get { return _selectedCompany; }
set
{
if (value == _selectedCompany)
return;
_selectedCompany = value;
OnPropertyChanged(nameof(SelectedCompany));
}
}
Just to clarify the Company class is actually an ENUM
DescriptionConverter:
public class CompanyDescriptionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var type = typeof(Company);
var name = Enum.GetName(type, value);
FieldInfo fi = type.GetField(name);
var descriptionAttrib = (DescriptionAttribute)
Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
return descriptionAttrib.Description;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
what i mean by inside my UI, is i have a list of companies set to a combobox item source, and when i change the combobox value to another company, it doesn't update in my source, it stay's as default.
My Enum might clarify the problem for someone:
[Description("Netpoint Solutions")]
Company1 = 0,
[Description("Blackhall Engineering")]
Company2 = 180,
Try to remove Mode=OneWayToSource and your event handler:
SelectionChanged="CompanyComboBox_SelectionChanged"
You don't need to handle the SelectionChanged event when you bind the SelectedItem property.
Also make sure that you set the DataContext to an instance of your class where the SelectedCompany property is defined.
Your Binding is defined as OneWayToSource. When you want it to be updated from the viewModel, you should set it to TwoWay.
See the documentation of Bindings for more details: https://msdn.microsoft.com/de-de/library/ms752347(v=vs.110).aspx
EDIT:
I skipped the part where you have an Enum as the source. I do not see, that you define the ItemsSource for the Combobox, where is this done? The value passed to the setter of SelectedCompany has to be in the Collection defined as ItemsSource.
For Enums, you can refer to this thread: How to bind an enum to a combobox control in WPF?
Im new here, I have built this small uwp app using binded ObservableCollection to a Listbox, I wanted to know how to change apearence of Textbox inside listbox. To be precise I have ObservableCollection which is made out of objects and one property of this object is a boolean. "UsersWithIndications.CheckedInOrOut" = boolean. I want to make it so if this boolean is true, textbox of this single User becomes green, if its false = red... Can You please show me a direction of resolving this issue? How can I access each individual textbox in this Listbox? If any more code is required, please let me know!
Xaml code for the page
App Launched, Listbox
Method 1:
Using Converter
Here is the code for Converter
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if ((string)value == "true")
return new SolidColorBrush(Colors.Green);
else
return new SolidColorBrush(Colors.Red);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Here is the code Data Binding
<Page.Resources>
<local:MyConverter x:Key="MyConverter"/>
</Page.Resources>
<TextBlock Name="MyOutput" Text="true" Foreground="{Binding Path=Text, Converter={StaticResource MyConverter}, ElementName=MyOutput}"/>
Method 2:
Using separate property for Foreground color
I am working on a windows universal app and I'm trying to work out data binding.
I have a listview which has an item template and data template in which a property of a custom class is bound.
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Textblock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This works fine an displays the names all instances of my custom class in the ObservableCollection I bind to the listview. I was wondering however if there is some way of modifying what is being bound before it is bound without changing the class itself.
I'm trying to bind a capitalisation of the string property Name so if the name was Test I want to bind TEST instead. Currently the way I'm doing this is to have a separate property called NameLabel which I populate like this
NameLabel = Name.ToUpper();
However this seems very messy and I was wondering if there's a neater way of doing it without creating a separate property?
You can use a Converter.
Create a StringToUpper.cs File with a StringToUpper Class which inherits form IValueConverter:
public class StringToUpper: IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
var valueString = value.ToString();
if (!string.IsNullOrEmpty(valueString))
{
return valueString.ToUpper();
}
return string.Empty;
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
// do nothing.
}
}
Add the resource of your created Converter:
...
xmlns:converter="clr-namespace:StringToUpper"
...>
<Window.Resources>
<converter:StringToUpper x:Key="StringToUpperConverter" />
</Window.Resources>
Add the converter:
<Textblock Text="{Binding Name, Converter={StaticResource StringToUpperConverter}}"/>
Here is a good Tutorial about Converters in WPF.
You could create a converter, that turns the value of a property into a form desired for the view (in your case, a simple capitalisation of the string).
Your converter class might look like this:
public class StringToUpperStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var valueString = value.ToString();
if (!string.IsNullOrEmpty(valueString))
{
return valueString.ToUpper();
}
return string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Your xaml might have this defined in the resource section:
<converters:StringToUpperStringConverter x:Key="StringToUpperStringConverter" />
And your binding would then look like this:
<Textblock Text="{Binding Name, Converter={StaticResource StringToUpperStringConverter}}"/>
I am using WPF. I am using datagrid to dynamically add items in it.
When the application is initially loaded, the datagrid is empty, or when all the items in the datagrid are remove, it only shows datagrid header.
How can I remove the header, and show a message like "Please insert an item." when the datagrid is empty.
I'd use an IValueConverter for this. Bind directly to the Items source, and when it's null/empty, then return Visibility.Collapsed. Add text notice as a TextBlock, and negate the converter using a parameter.
<TextBlock Text="There are no items"
Visibility="{Binding Items,
Converter={StaticResource ItemsToVisibilityConverter},ConverterParameter=negate}" />
<DataGrid Visibility="{Binding Items,
Converter={StaticResource ItemsToVisibilityConverter}}">
</DataGrid>
And the converter has to make use of the ConverterParameter:
public class ItemsToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var items = value as IEnumerable<object>;
bool isVisible = items != null && items.Count() > 0;
if ((string)parameter == "negate") isVisible = !isVisible;
return isVisible ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}