Automatic data update in WPF - c#

<Window x:Class="Binding2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Vertical">
<StackPanel HorizontalAlignment="Left" Name="stackPanel1" VerticalAlignment="Top" Width="165" Orientation="Horizontal">
<TextBlock Height="20" Name="_sourceTextBlock" Text="Source" Width="67" />
<TextBox Height="20" Name="_sourceTextBox" Width="92" />
</StackPanel>
<StackPanel HorizontalAlignment="Left" Name="stackPanel2" VerticalAlignment="Top" Width="165" Orientation="Horizontal">
<TextBlock Height="20" Name="_destTextBlock" Text="Destination" Width="67" />
<TextBox Height="20" Name="_destTextBox" Width="92" />
</StackPanel>
</StackPanel>
</Window>
I have two text boxes. How can I program that the value in Destination text box is automatically modified based on the value in Source text box? For example, when the value in Source is "abc", how can I make the value in Destination is automaticaly "x" + "abc" + "x"? Or, make destination the number 10*source.
ADDED
I also found a way to get the result when the source is more than one - Bind an element to two sources

That's easy using MVVM :
public class MainWindowViewModel : ViewModelBase
{
private string _source;
public string Source
{
get { return _source; }
set
{
_source = value;
OnPropertyChanged("Source");
OnPropertyChanged("Destination");
}
}
public string Destination
{
get { return "x" + _source + "x"; }
}
}
Use that class as the DataContext for your view, and bind one TextBox to Source (TwoWay), and the other to Destination (OneWay):
<StackPanel Orientation="Vertical">
<StackPanel HorizontalAlignment="Left" Name="stackPanel1" VerticalAlignment="Top" Width="165" Orientation="Horizontal">
<TextBlock Height="20" Name="_sourceTextBlock" Text="Source" Width="67" />
<TextBox Height="20" Name="_sourceTextBox" Width="92" Text="{Binding Source, Mode=TwoWay}" />
</StackPanel>
<StackPanel HorizontalAlignment="Left" Name="stackPanel2" VerticalAlignment="Top" Width="165" Orientation="Horizontal">
<TextBlock Height="20" Name="_destTextBlock" Text="Destination" Width="67" />
<TextBox Height="20" Name="_destTextBox" Width="92" Text="{Binding Destination, Mode=OneWay}" IsReadOnly="True" />
</StackPanel>
</StackPanel>
Anyway, if you're building a non-trivial WPF application, I strongly recommend moving to the MVVM pattern, in the long-term your app will be much easier to maintain.

There are a couple of approaches you could use, the first is purely within the UI by using Elementname binding:
<TextBox Height="20" Name="_destTextBox"
Text="{Binding Path=Text, ElementName=_sourceTextBox}"/>
This will synchronize the TextBoxes, add a ValueConverter if you want to add text before and after. For example:
public class MyValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return "x" + (string)value + "x";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And used as follows:
<Window x:Class="Binding2.MainWindow"
....
xmlns:local="clr-namespace:Binding2"
....
<Window.Resources>
<MyValueConverter x:Key="MyValueConverter"/>
</Window.Resources>
...
<TextBox Height="20" Name="_destTextBox"
Text="{Binding Path=Text, ElementName=_sourceTextBox, Converter={StaticResource MyValueConverter}}"/>
The other approach would be to create a ViewModel layer than binds to your view and performs this logic.

quickest way would be to use ValueConverter or have 2 separate properties in your ViewModel so that one is bound to Source Property in VM, and other derives from the Source (i.e. decorates it with "X" and returns it)
Example(you should implement INotifyPropertyChanged so that Binding engine picks up the Destination change and refreshed the textbox in your GUI):
public string Source { get; set; }
public string Destination {get{
return "X" + Source + "X"
}
}

You can use StringFormat, i.e.: StringFormat='x{0}x', e.g.:
<TextBox Height="20" Name="_destTextBox" Width="92"
Text="{Binding ElementName=_sourceTextBox, Path=Text, StringFormat='x{0}x'}" />

Related

c# wpf in a listbox doing binding with checkbox to an object within another object

I have a Listbox which consists of elements that looks like this.
class ItemForListbox
{
public string path { get; set; }
public string file { get; set; }
public InstallationPackageChoice choices { get; set; }
public KeepKill keepKill { get; set; }
}
The choices and keepKill are objects.
My XAML for the listbox has this DataTemplate
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Name="btnPackageVersion" Style="{StaticResource ListBoxButtonFormat}" Content ="Package version" Click="btnInstallPackage_Click" HorizontalAlignment="Right"/>
<TextBlock Name="txtBlkPath" Text="{Binding path}" FontSize="10" Width="500" Height="20" Margin="10,10,0,0"/>
<Button Name="btnFilterPath" Style="{StaticResource ListBoxButtonFormat}" Content ="Filter path" Click="btnFilterpath_Click" HorizontalAlignment="Right"/>
<TextBlock Name="txtBlkFile" Text="{Binding file}" FontSize="10" Width="150" Height="20" Margin="10,10,0,0"/>
<Button Name="btnFilterfile" Style="{StaticResource ListBoxButtonFormat}" Content="Filter file" Click="btnFilterfile_Click" HorizontalAlignment="Right"/>
<CheckBox Name="chkBxKeep" Content="Keep" VerticalAlignment="Center" HorizontalAlignment="Right" IsChecked="True" Checked="chkBxKeep_Checked"/>
<CheckBox Name="chkBxKill" Content="Kill" VerticalAlignment="Center" HorizontalAlignment="Right" Checked="chkBxKill_Checked"/>
<Separator Name="MySeparator"
Height="3"
Width="Auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Background="Red" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
The two checkboxes underlying data is the killKeep object in the Listbox element object.
The problem is that i would like to have a radiobutton functionality of the two checkboxes, so when i check a checkbox, the other one unchecks. The reason i dont use radiobuttons are that i simply do not understand them in regards to binding. But now i find i also do not know how to do this binding with the checkboxes.
I hope someone can help me.
You can use binding with a converter to bind IsChecked property of checkboxes:
<Window.Resources>
<local:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
</Window.Resources>
...
<CheckBox Name="chkBxKeep" Content="Keep" VerticalAlignment="Center" HorizontalAlignment="Right" IsChecked="True" Checked="chkBxKeep_Checked"/>
<CheckBox Name="chkBxKill" Content="Kill" VerticalAlignment="Center" HorizontalAlignment="Right" Checked="chkBxKill_Checked"
IsChecked="{Binding ElementName=chkBxKeep, Path=IsChecked, Converter={StaticResource InverseBooleanConverter}}"/>
Converter
public class InverseBooleanConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is bool)
{
return !(bool)value;
}
return true;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Convert(value, targetType, parameter, culture);
}
#endregion
}

Could not pass values from view to viewmodel through commands

I am implementing MVVM pattern for my application. I have my Views, ViewModel, Model and Commands and Converters being implemented. Now I am not able to pass my textboxes values from my datatemplate to my ViewModel through the command binding. I am able to click on the button to attempt the update process but its not able to pass the textboxes value. Are there something i need to change on my command class?
Here is my XAML:
<DataGrid AutoGenerateColumns="False" Grid.Row="2" Grid.ColumnSpan="4" Grid.RowSpan="3" x:Name="productionLineConfigDataGrid" Margin="70,0.2,70,0" ItemsSource="{Binding listAllProductionLineConfigs}">
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="ID: " VerticalAlignment="Center" />
<TextBlock x:Name="txtBlockLineId" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineId, Mode=TwoWay}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel>
<Button x:Name="btnUpdate" Content="Update" VerticalAlignment="Center" HorizontalAlignment="Right" Click="btnUpdate_Click" Command="{Binding DataContext.updateProductionLineConfigCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:production_line_config_home}}}" CommandParameter="{Binding ProductionLineConfig}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</DataGrid>
Here is the method from my ViewModel:
public ProductionLineConfig ProductionLineConfig
{
get { return productionlineconfig; }
set
{
productionlineconfig = value;
OnPropertyChanged("ProductionLineConfig");
}
}
This is the error message i am getting:
System.Windows.Data Error: 40 : BindingExpression path error: 'ProductionLineConfig' property not found on 'object' ''ProductionLineConfig' (HashCode=47309994)'. BindingExpression:Path=ProductionLineConfig; DataItem='ProductionLineConfig' (HashCode=47309994); target element is 'Button' (Name=''); target property is 'CommandParameter' (type 'Object')
I have included the image for my application here
This is the entire xaml code here and this is the entire viewmodel code here
I'm only going to take a guess at this.
Assuming ProductionLineConfig is what you are binding to for ProductionLineId in the template. Then you probably are just wanting to pass your binding source as the command parameter
CommandParameter="{Binding}"
When {Binding} is empty, it means the Binding is bound to whatever Source there is. Which is also just shorthand for...
{Binding DataContext,RelativeSource={RelativeSource Self}}.
In turn (if the stars align), then it should be your ProductionLineConfig
Based on your code source, I made a sample implementation, to achieve your requirement.
Sample VM:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApp5.ViewModels
{
public class ProductionLineConfigViewModel : INotifyPropertyChanged
{
public CustomCommand<ProductionLineConfig> UpdateCommand { get; }
public ProductionLineConfigViewModel()
{
PopulateProductionLineConfigs();
UpdateCommand = new CustomCommand<ProductionLineConfig>(UpdateConfig, (u) => true);
}
private ObservableCollection<ProductionLineConfig> _listAllProductionLineConfigs;
public ObservableCollection<ProductionLineConfig> listAllProductionLineConfigs
{
get { return _listAllProductionLineConfigs; }
set
{
_listAllProductionLineConfigs = value;
OnPropertyChanged();
}
}
// Call this from constructor.
private void PopulateProductionLineConfigs()
{
listAllProductionLineConfigs = new ObservableCollection<ProductionLineConfig>
{
new ProductionLineConfig
{
ProductionLineId = 1,
ProductionLineCode = "001",
ProductionLineCreatedDate = DateTime.Today.Date,
ProductionLineName = "safdsf",
ProductionLineStatus = true
},
new ProductionLineConfig
{
ProductionLineId = 1,
ProductionLineCode = "002",
ProductionLineCreatedDate = DateTime.Today.Date,
ProductionLineName = "sadfadfsdf",
ProductionLineStatus = true
}
};
}
private void UpdateConfig(ProductionLineConfig config)
{
MessageBox.Show("Line Name update: " + config.ProductionLineName);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class ProductionLineConfig
{
public int ProductionLineId { get; set; }
public string ProductionLineCode { get; set; }
public string ProductionLineName { get; set; }
public bool ProductionLineStatus { get; set; }
public DateTime ProductionLineCreatedDate { get; set; }
}
}
Sample XAML:
<Window x:Name="Root" x:Class="WpfApp5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:WpfApp5.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<viewModels:ProductionLineConfigViewModel/>
</Window.DataContext>
<Grid Background="#FF006E8C">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.ColumnSpan="4" Content="KAD ShopFloor System" HorizontalAlignment="Center" Margin="10" FontWeight="Bold" FontSize="30" FontFamily="Segoe UI" Foreground="White"/>
<Separator Grid.ColumnSpan="4" Grid.RowSpan="3" Background="White" Margin="0,-35,-0.4,39.2"/>
<DataGrid AutoGenerateColumns="False" Grid.Row="2" Grid.ColumnSpan="4" Grid.RowSpan="3" x:Name="productionLineConfigDataGrid" Margin="70,0.2,70,0"
ItemsSource="{Binding DataContext.listAllProductionLineConfigs, ElementName=Root}">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding ProductionLineId, Mode=TwoWay}"/>
<DataGridTextColumn Header="Production Line Code" Binding="{Binding ProductionLineCode, Mode=TwoWay}"/>
<DataGridTextColumn Header="Production Line Name" Binding="{Binding ProductionLineName, Mode=TwoWay}"/>
<DataGridTextColumn Header="Status" Binding="{Binding ProductionLineStatus, Mode=TwoWay}"/>
<DataGridTextColumn Header="Created Date" Binding="{Binding ProductionLineCreatedDate, Mode=TwoWay}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border BorderThickness="0" Background="BlanchedAlmond" Padding="10">
<StackPanel Orientation="Vertical" x:Name="stck">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="ID: " VerticalAlignment="Center" />
<TextBlock x:Name="txtBlockLineId" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Line Code: " VerticalAlignment="Center" />
<TextBlock x:Name="txtBlockLineCode" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Line Name: " VerticalAlignment="Center" />
<TextBox x:Name="txtLineName" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
</StackPanel>
<!--<StackPanel Orientation="Horizontal">
<TextBlock FontSize="12" Text="Status: " VerticalAlignment="Center" />
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}},
Path=DataContext.Statusstring}" SelectedValue="{Binding ProductionLineStatus, Converter={StaticResource statusToBooleanConverter}, Mode=TwoWay}" x:Name="cbProductionLineStatus" FlowDirection="LeftToRight" FontSize="16" Foreground="MidnightBlue"
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
</StackPanel>-->
<StackPanel>
<Button x:Name="btnUpdate" Content="Update" VerticalAlignment="Center" HorizontalAlignment="Right"
Command="{Binding DataContext.UpdateCommand, ElementName=Root}"
CommandParameter="{Binding}" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</Window>
Sample output:
Key changes here,
You need to change your list to observable collection
Create a custom command that accepts an object, see this post: [UWP/MVVM]Enable/Disable Button in RadDataGrid Data Template Column that have commands bound to them upon conditions
Command Parameter should be the iterated item, can be achieve by CommandParameter={Binding}
In you two way bindings, make sure to add UpdateSourceTrigger=PropertyChanged

filter xaml gridview with combo box

I am just starting off with windows 8 apps development and I want to be able to filter a gridview using the selected value in a combobox
my xaml page code behind
public sealed partial class MainPage : Page
{
public ObservableCollection<Recording> MyMusic = new ObservableCollection<Recording>();
public MainPage()
{
this.InitializeComponent();
// Add items to the collection.
MyMusic.Add(new Recording("Chris Sells", "Chris Sells Live",
new DateTime(2008, 2, 5)));
MyMusic.Add(new Recording("Luka Abrus",
"The Road to Redmond", new DateTime(2007, 4, 3)));
MyMusic.Add(new Recording("Jim Hance",
"The Best of Jim Hance", new DateTime(2007, 2, 6)));
// Set the data context for the combo box.
//ComboBox1.DataContext = MyMusic;
this.DataContext = new CollectionViewSource { Source = MyMusic };
}
}
Class
public class Recording
{
public Recording() { }
public Recording(string artistName, string cdName, DateTime release)
{
Artist = artistName;
Name = cdName;
ReleaseDate = release;
}
public string Artist { get; set; }
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
// Override the ToString method.
public override string ToString()
{
return Name + " by " + Artist + ", Released: " + ReleaseDate.ToString("d");
}
}
Xaml mark up
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ComboBox x:Name="ComboBox1" HorizontalAlignment="Left" Margin="542,108,0,0" VerticalAlignment="Top" Width="360" ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Artist:" Margin="2" />
<TextBlock Text="{Binding Artist}" Margin="2" />
<TextBlock Text="CD:" Margin="10,2,0,2" />
<TextBlock Text="{Binding Name}" Margin="2" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!--<StackPanel x:Name="RecordingDetails" Margin="542,150,10,30">
<TextBlock Text="{Binding Artist}" FontWeight="Bold" FontSize="30" />
<TextBlock Text="{Binding Name}" FontStyle="Italic" FontSize="30" />
<TextBlock Text="{Binding ReleaseDate}" FontSize="30" />
</StackPanel>-->
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.RowSpan="2"
Padding="116,137,40,46"
ItemsSource="{Binding}"
SelectionMode="None"
IsSwipeEnabled="false" >
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}" Name="test">
<TextBlock Text="{Binding Artist}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0"/>
<TextBlock Text="{Binding Name}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
<TextBlock Text="{Binding ReleaseDate}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid GroupPadding="0,0,70,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
so essentially I just need to filter the gridview dynamically using combo box value selected.
Kindly appreciate help and guidaince please.
This is a msdn example.
You can refer this msdn page link for further details.
UserControl
<UserControl x:Class="TestDataBindingQS.Page2"
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="using:TestDataBindingQS"
mc:Ignorable="d"
d:DesignHeight="768" d:DesignWidth="1366">
<UserControl.Resources>
<local:StringFormatter x:Key="StringConverter"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="#FF0C0C0C">
<StackPanel Width="750" Height="200"
VerticalAlignment="Center" HorizontalAlignment="Center">
<ComboBox x:Name="ComboBox1" ItemsSource="{Binding}"
Foreground="Black" FontSize="30" Height="50" Width="750">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="Artist:" Margin="2" />
<TextBlock Text="{Binding Artist}" Margin="2" />
<TextBlock Text="CD:" Margin="10,2,0,2" />
<TextBlock Text="{Binding Name}" Margin="2" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!--The UI for the details view-->
<StackPanel x:Name="RecordingDetails">
<TextBlock Text="{Binding Artist}" FontSize="30" FontWeight="Bold" />
<TextBlock Text="{Binding Name}" FontSize="30" FontStyle="Italic" />
<TextBlock Text="{Binding ReleaseDate,
Converter={StaticResource StringConverter},
ConverterParameter=Released: \{0:d\}}" FontSize="30" />
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
converter class
public class StringFormatter : IValueConverter
{
// This converts the value object to the string to display.
// This will work with most simple types.
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
// Retrieve the format string and use it to format the value.
string formatString = parameter as string;
if (!string.IsNullOrEmpty(formatString))
{
return string.Format(culture, formatString, value);
}
// If the format string is null or empty, simply
// call ToString() on the value.
return value.ToString();
}
// No need to implement converting back on a one-way binding
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And this produces the following output

Windows Phone 8 TextBlock

How do I hide a TextBlock in Windows Phone 8 if it has no text?
<StackPanel>
<TextBlock Text="{Binding Name}" FontSize="22" Margin="0,5,10,0" TextWrapping="NoWrap" TextAlignment="Center" TextTrimming="WordEllipsis" />
<Image Source="{Binding Icon}" MaxWidth="36" MaxHeight="36" HorizontalAlignment="Left" Margin="10,-33,10,10" Stretch="Fill"/>
<TextBlock Text="{Binding Description}" FontSize="14" Margin="10,0,10,5" MaxHeight="60" TextWrapping="Wrap" TextTrimming="WordEllipsis" />
</StackPanel>
I would like to hide the textblock "description" if it doesn't have any text inside it. How would this be possible?
It's a multiple "viewmodel" textblock, therefore it has no name and can't be checked individually, due to performance issues of loading over 20+ every 5 - 15 seconds.
You will need to create an IValueConverter that analyses the length of the string,
public class HideEmptyStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var input = (string)value;
return string.IsNullOrWhiteSpace(input) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
add an instance of the converter to your page's resources and then bind the Visibility property to the description using that converter...
<TextBlock Text="{Binding Description}" Visibility="{Binding Description, Converter={StaticResource HideEmptyStringConverter}}" FontSize="14" Margin="10,0,10,5" MaxHeight="60" TextWrapping="Wrap" TextTrimming="WordEllipsis" />

Binding to a depencency property doesn't work

I derived ImageButton from Button class. I want to be able to set text on it using custom property.
ImageButton XAML
<Button x:Class="MyProject.ImageButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="50" Width="75" Template="{DynamicResource BlueButton}">
<StackPanel>
<TextBlock Text="{Binding Path = ImageButton.ButtonText}" TextWrapping="Wrap" Foreground="White"/>
</StackPanel>
</Button>
ImageButton code behind
public partial class ImageButton : Button
{
public string ButtonText
{
get { return (string)GetValue(ButtonTextProperty); }
set { SetValue(ButtonTextProperty, value); }
}
public static readonly DependencyProperty ButtonTextProperty =
DependencyProperty.Register("ButtonText", typeof(string), typeof(ImageButton), new UIPropertyMetadata(string.Empty));
public ImageButton()
{
InitializeComponent();
}
}
Client code:
<local:ImageButton Margin="114,15.879,96,15.878" Grid.Row="2" ButtonText="test"/>
No text is being shown on the button. For some reason the binding doesn't seem to be taking place. What am I doing wrong?
You don’t have a DataContext set, so the data binding doesn’t know which source object it should bind to.
I find that the easiest way to resolve this is to give your outer control a name, and reference it using ElementName in your binding:
<Button x:Class="MyProject.ImageButton"
x:Name="myImageButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="50" Width="75" Template="{DynamicResource BlueButton}">
<StackPanel>
<TextBlock Text="{Binding ElementName=myImageButton, Path=ButtonText}"
TextWrapping="Wrap" Foreground="White"/>
</StackPanel>
</Button>
Change this
<TextBlock Text="{Binding Path = ImageButton.ButtonText}"
to
<TextBlock Text="{Binding Path = ButtonText}"

Categories

Resources