<Border Grid.Row="0" Height="auto" x:Name="BorderEcs" Background="#9494a5" BorderThickness="1,0,1,1" BorderBrush="#9494a5" CornerRadius="10,10,0,0">
<StackPanel Height="auto">
<Label x:Name="LblTitl" Content="" Margin="5,0,0,0" Height="auto" Foreground="#FFFFFF" FontFamily="Century Gothic" FontSize="13" />
<DataGrid Width="{Binding ControlWidth, RelativeSource={RelativeSource Self},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Height="{Binding ControlHeight, RelativeSource={RelativeSource Self},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
CellStyle="{StaticResource DataGridContentCellCentering}"
RowStyle="{StaticResource RowStyle}"
ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}"
Style="{StaticResource DataGridStyle}"
AlternatingRowBackground="White"
AlternationCount="2">
</DataGrid>
</StackPanel>
{
public partial class UCDataGrid : UserControl,INotifyPropertyChanged
{
public UCDataGrid()
{
InitializeComponent();
DataContext = this;
}
public static DependencyProperty ControlHeightProperty =
DependencyProperty.Register("ControlHeight", typeof(int), typeof(UCDataGrid));
public static DependencyProperty ControlWidthProperty =
DependencyProperty.Register("ControlWidth", typeof(int), typeof(UCDataGrid));
public event PropertyChangedEventHandler PropertyChanged;
public int ControlHeight
{
get { return (int)GetValue(ControlHeightProperty); }
set { SetValue(ControlHeightProperty, value);
OnProperyChanged("ControlHeight");
}
}
public int ControlWidth
{
get { return (int)GetValue(ControlWidthProperty); }
set { SetValue(ControlWidthProperty, value); OnProperyChanged("ControlWidth"); }
}
public void OnProperyChanged(string propName = null)
{
PropertyChangedEventHandler propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
}
<us:UCDataGrid x:Name="d" ControlWidth="1" ControlHeight="10" />
Please try below code, It worked for me. For simplicity, I have just included code for ControlWidth
public partial class UCDataGrid : UserControl
{
public UCDataGrid()
{
InitializeComponent();
}
public static DependencyProperty ControlWidthProperty =
DependencyProperty.Register("ControlWidth", typeof(double), typeof(UCDataGrid),new UIPropertyMetadata());
public double ControlWidth
{
get { return (double)GetValue(ControlWidthProperty); }
set { SetValue(ControlWidthProperty, value); }
}
}
Now set Name to your UserControl in xaml and access it to set the binding. For the time being remove all the styles and check to make sure the width and height are not being set at any other place.
<UserControl Name="root">
<Border Grid.Row="0" Height="auto" x:Name="BorderEcs" Background="#9494a5" BorderThickness="1,0,1,1" BorderBrush="#9494a5" CornerRadius="10,10,0,0">
<StackPanel Height="auto">
<Label x:Name="LblTitl" Content="" Margin="5,0,0,0" Height="auto" Foreground="#FFFFFF" FontFamily="Century Gothic" FontSize="13" />
<DataGrid Width="{Binding ElementName=root, Path=ControlWidth, UpdateSourceTrigger=PropertyChanged}"
Height="{Binding ElementName=root, Path=ControlHeight, UpdateSourceTrigger=PropertyChanged}"
CellStyle="{StaticResource DataGridContentCellCentering}"
RowStyle="{StaticResource RowStyle}"
ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}"
Style="{StaticResource DataGridStyle}"
AlternatingRowBackground="White"
AlternationCount="2">
</DataGrid>
</StackPanel>
</UserControl>
Hope it helps
Related
I cannot get a change in the UI (TextBox) when selecting a tree item. When I select a tree item, the property and the text should change. But this does not happen. Property changes, but text remains the same. At first I tried to cause a property change in MainViewModel, but ran into the same problem: the property changes but the UI remains unchanged.
public class BindableSelectedItemBehavior : Behavior<TreeView>, INotifyPropertyChanged
{
MainViewModel vm = new MainViewModel();
private string _message;
public string Message
{
get
{
return _message;
}
set
{
_message = value;
OnPropertyChanged("Message");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));
private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var item = e.NewValue as TreeViewItem;
if (item != null)
{
item.SetValue(TreeViewItem.IsSelectedProperty, true);
}
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
if (AssociatedObject != null)
{
AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
}
}
private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
SelectedItem = e.NewValue;
string name = GetName((Item)SelectedItem);
Message = "edgddgdgdg";
}
public string GetName(Item item)
{
string circ = item.Name;
return circ;
}
}
}
<UserControl x:Class="WpfApp3.TreeViewTextChange"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp3"
xmlns:vm="clr-namespace:WpfApp3.ViewModel"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<vm:BindableSelectedItemBehavior/>
</UserControl.DataContext>
<Grid>
<TextBox Grid.Row="1" Grid.Column="2" Text="{Binding Path=Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="Aqua" Width="200" Height="50"/>
</Grid>
</UserControl>
Used a debugger - property changes but does not change textbox in UserControl.
My MainViewModel
class MainViewModel : BindableBase
{
MainModel mainModel = new MainModel();
private ICollectionView root;
public MainViewModel()
{
OpenSth = new DelegateCommand(DisplayItemTree);
ShowCheck = new DelegateCommand(ShowCheckedItemsCommand);
Sth = new DelegateCommand(Changetext);
TextChengedCommand = new DelegateCommand<object>(textChange);
}
public ICommand OpenSth { get; }
public ICommand ShowCheck { get; }
public ICommand Sth { get; }
public ICommand TextChengedCommand { get; }
private void textChange(object obj)
{
var str = obj as string;
}
public void DisplayItemTree()
{
var itemTree = mainModel.GetItemsTree();
Root = CollectionViewSource.GetDefaultView(itemTree);
Root.Filter = new Predicate<object>((item) =>
{
var realItem = (Item)item;
return true;
});
Root.Refresh();
}
public ICollectionView Root
{
get => root;
set => SetProperty(ref root, value);
}
public void ShowCheckedItemsCommand()
{
var str = new StringBuilder();
List<Item> items = mainModel.FindCheckedItem();
if (items.Count == 0)
{
str.Append("No selected items");
}
else
{
foreach (var item in items)
{
str.Append(item.Name);
}
}
MessageBox.Show(str.ToString());
}
private string _name;
public string TextText
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged("TextText");
}
}
public void Changetext()
{
TextText = "dggg";
}
}
}
And xaml code
<Window x:Class="WpfApp3.MainWindow"
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="clr-namespace:WpfApp3"
xmlns:beh="clr-namespace:WpfApp3.ViewModel"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ii="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:prism="http://www.codeplex.com/prism"
mc:Ignorable="d"
xmlns:vm="clr-namespace:WpfApp3.ViewModel"
xmlns:bh="clr-namespace:WpfApp3.ViewModel"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<DockPanel Grid.Column="1" Grid.Row="0" Grid.RowSpan="2">
<TextBox x:Name="searchBox" DockPanel.Dock="Top" Height="30" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="1" Text="{Binding SearchText}">
<ii:Interaction.Triggers>
<ii:EventTrigger EventName="TextChenged">
<ii:InvokeCommandAction Command="{Binding TextChengedCommand}" CommandParameter="{Binding ElementName=searchBox, Path=Text}"/>
</ii:EventTrigger>
</ii:Interaction.Triggers>
</TextBox>
<DockPanel DockPanel.Dock="Bottom">
<Button Content="Get TreeView" Command="{Binding OpenSth}" Width="100"/>
<Button Content="Show Check Item" Command="{Binding ShowCheck}" Width="100"/>
</DockPanel>
<TreeView BorderBrush="Black" BorderThickness="1" ItemsSource="{Binding Root}">
<i:Interaction.Behaviors>
<beh:BindableSelectedItemBehavior SelectedItem="{Binding SelectedNode, Mode=TwoWay}"/>
</i:Interaction.Behaviors>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Sub}">
<DockPanel>
<CheckBox IsChecked="{Binding CheckedItem}" Margin="0 8 0 8" VerticalAlignment="Center" DockPanel.Dock="Left"/>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" DockPanel.Dock="Right"/>
</DockPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</DockPanel>
<DataGrid AutoGenerateColumns="False" Height="210" HorizontalContentAlignment="Left" Name="DataGrid" VerticalAlignment="Top" Grid.Column="2" Grid.Row="0" Margin="0,0,0,0" ItemsSource="{Binding ListOfCircuets}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Length}" MinWidth="50"/>
<DataGridTextColumn Binding="{Binding dU}" MinWidth="50"/>
<DataGridTextColumn Binding="{Binding Cable}" MinWidth="50"/>
<DataGridTextColumn Binding="{Binding I}" MinWidth="50"/>
</DataGrid.Columns>
</DataGrid>
<TextBox Grid.Row="1" Grid.Column="2" Text="{Binding TextText, Mode=TwoWay}" Background="Aqua" Width="200" Height="50"/>
<Button Content="Show Check Item" Command="{Binding Sth}" Width="100"/>
<local:TreeViewTextChange Grid.Row="1" Grid.Column="2"></local:TreeViewTextChange>
</Grid>
</Window>
For my current projet i want to make an UI where information are displayed on "tile" which i designed as a Grid with other Label and progress bar into. But i can't figure out how to make those tiles displayed on my main grid.
I already tried Gridview that didn't work with the exemples on the web and making someway without grid isn't really easy.
This is the grid to insert as many times as needed
<Grid Margin="10" Background="AntiqueWhite" Grid.Row="0" Grid.Column="0">
<Label Content="{Binding fieldname}" FontFamily="Arial Black" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,20,0,0"/>
<Label Content="{Binding datebegin}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="85,85,0,0" FontFamily="Arial Black" FontSize="18" />
<Label Content="{Binding dateend}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="285,85,0,0" FontFamily="Arial Black" FontSize="18" />
<ProgressBar Margin="0,150,0,0" Value="{Binding progression}" Background="White" BorderBrush="Black" VerticalAlignment="Top" Height="50" />
</Grid>
I need a way to add the exact tile produced into a grid (or anything else that can get onto a scrollviewer with 3 column and unlimited lines obviously).
Below is the xmal. I have used ItemsControl and the WrapPanel as ItemsPanelTemplate to wrap the ItemsControl's items
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Content="Add" Height="26" Width="75" Command="{Binding Add}" Grid.Row="0"/>
<ScrollViewer Height="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.Row="1">
<ItemsControl ItemsSource="{Binding Items}" HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="10,10,0,0" BorderBrush="Black" BorderThickness="1">
<StackPanel Width="200" Height="Auto">
<Label Content="{Binding fieldname}" FontFamily="Arial Black" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,10,0,0"/>
<Label Content="{Binding datebegin}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,10,0,0" FontFamily="Arial Black" FontSize="18" />
<Label Content="{Binding dateend}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,10,0,0" FontFamily="Arial Black" FontSize="18" />
<ProgressBar Value="{Binding progression}" Margin="5,10,5,10" Background="White" BorderBrush="Black" VerticalAlignment="Top" Height="20" />
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
And the viewmodel is
public class Item
{
public string fieldname
{
get;
set;
}
public string datebegin
{
get;
set;
}
public string dateend
{
get;
set;
}
public string progression
{
get;
set;
}
public Item(int number)
{
fieldname = "Filed name " + number;
datebegin = "12-12-12";
dateend = "14-12-12";
progression = (5 * number).ToString();
}
}
public class ViewModel
{
public ICollection<Item> Items
{
get;
private set;
}
public ViewModel()
{
Items = new ObservableCollection<Item>();
}
public ICommand Add
{
get
{
return new RelayCommand((a) =>
{
Items.Add(new Item(Items.Count));
});
}
}
}
Relaycommand
public class RelayCommand : ICommand
{
private Action<object> execute;
private Predicate<object> canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
Im missing something but i have no idea what :(
I've bind IEnumerable collection to combobox. I would like to use its selected value as parameter for shutdown command, however when i press start button it doesn't load selected values.
I've followed few tutorials to understand MVVM but there is still something missing but i cant figured out what.
Here is MainWindow.xaml :
<grid>
<StackPanel>
<!--Title label-->
<TextBlock Text="Wyłącz komputer za:" Margin="5"/>
<!-- Blocks used to set hours and minutes-->
<StackPanel Orientation="Horizontal">
<TextBlock Text="Godziny:" Margin="5"/>
<ComboBox x:Name="HoursCB" Margin="5" Width="40" ItemsSource="{Binding myHours}" SelectedValue="{Binding selectedHours, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="Minuty:" Margin="5" />
<ComboBox x:Name="MinutesCB" Margin="5" Width="40" ItemsSource="{Binding myMinutes}" SelectedValue="{Binding selectedMinutes, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel >
<!-- Timer -->
<StackPanel Orientation="Horizontal">
<Label x:Name="HHLabel" Content="{Binding selectedHours}" FontSize="30" HorizontalAlignment="Center" Width="45"/>
<Label x:Name="Colon1" Content=":" FontSize="30" HorizontalAlignment="Center" Width="25"/>
<Label x:Name="MMLabel" Content="{Binding selectedMinutes}" FontSize="30" HorizontalAlignment="Center" Width="45"/>
<Label x:Name="Colon2" Content=":" FontSize="30" HorizontalAlignment="Center" Width="25"/>
<Label x:Name="SSLabel" Content="00" FontSize="30" HorizontalAlignment="Right" Width="45"/>
</StackPanel>
<!-- Start Button -->
<Button Content="uruchom odliczanie" Margin="5" Command="{Binding StartCommand}" />
<!-- Stop Button-->
<Button Content="Zatrzymaj odliczanie" Margin="5" Command="{Binding StopCommand}"/>
</StackPanel>
</grid>
and here is view model :
class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
StartCommand = new AddNameCommand(this);
}
class AddNameCommand : ICommand
{
MainWindowViewModel parent;
public AddNameCommand(MainWindowViewModel parent)
{
this.parent = parent;
parent.PropertyChanged += delegate { CanExecuteChanged?.Invoke(this, EventArgs.Empty); };
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{ return true; }
public void Execute(object parameter)
{
int num = parent.SelectedHours * 3600 + parent.SelectedMinutes * 60;
MessageBox.Show($"Shutting down the computer in {num} !");
//Process.Start("shutdown", string.Format("/s /t {0}", num));
}
}
public ICommand StartCommand { get; private set; }
/// <summary>
/// Combobox Items.
/// </summary>
//public IEnumerable<int> myHours = Enumerable.Range(0, 23);
//public IEnumerable<int> myMinutes = Enumerable.Range(1, 59);
public ObservableCollection<int> myHours { get; set; } = new ObservableCollection<int>(Enumerable.Range(0, 23));
public ObservableCollection<int> myMinutes { get; set; } = new ObservableCollection<int>(Enumerable.Range(1, 59));
/// <summary>
/// Selected time properties.
/// </summary>
public int SelectedMinutes
{
get { return mSelectedMinutes; }
set
{
if (value == mSelectedMinutes)
return;
mSelectedMinutes = value;
OnPropertyChanged();
}
}
int mSelectedMinutes;
public int SelectedHours
{
get { return mSelectedHours; }
set
{
if (value == mSelectedHours)
return;
mSelectedHours = value;
OnPropertyChanged();
}
}
int mSelectedHours;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = null)
{ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
}
You should change your xaml to the following (note the case sensitive SelectedHours/Minutes):
<!-- Blocks used to set hours and minutes-->
<StackPanel Orientation="Horizontal">
<TextBlock Text="Godziny:" Margin="5"/>
<ComboBox x:Name="HoursCB" Margin="5" Width="40" ItemsSource="{Binding myHours}" SelectedValue="{Binding SelectedHours, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="Minuty:" Margin="5" />
<ComboBox x:Name="MinutesCB" Margin="5" Width="40" ItemsSource="{Binding myMinutes}" SelectedValue="{Binding SelectedMinutes, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel >
Binding errors can be easily detected by opening the Output Window in Visual Studio and looking for the following:
System.Windows.Data Error: 40 : BindingExpression path error: 'selectedHours' property not found on 'object' ''MainWindowViewModel' (HashCode=46431654)'. BindingExpression:Path=selectedHours; DataItem='MainWindowViewModel' (HashCode=46431654); target element is 'ComboBox' (Name='HoursCB'); target property is 'SelectedValue' (type 'Object')
You have not binded the Selected Values of combo boxes to the right property in the View Model. Just change "selectedHours" to "SelectedHours" and "selectedMinutes" to "SelectedMinutes" in your XAML to bind it properly.
You code is behaving like i expedted it. Your problem is the Enumerable.Range function. It starts with an inclusive 0 and then counts up 23 times Inclunding 0
I need to change the boldness of text in list item on first selection.
Xaml:
<DockPanel >
<TextBox DockPanel.Dock="Top" Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<ListBox x:Name="list" ItemsSource="{Binding EmailsCollection}" SelectedItem="{Binding SelectedItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="{Binding Sender}" Name="SenderLabel" FontWeight="{Binding IsRead, Converter={StaticResource Converter}}"/>
<!--Style="{StaticResource Sender}"-->
<Label Grid.Row="1" Content="{Binding Subject}" FontSize="12" HorizontalAlignment="Left" />
<Label Grid.Column="1" Content="{Binding Date}" FontSize="12" HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
View model:
public Email SelectedItem
{
get
{
return _selectedItem;
}
set
{
_selectedItem = value;
_selectedItem.IsRead = true;
OnPropertyChanged(this,"SelectedItem");
}
}
Model:
public bool IsRead
{
get { return _isRead; }
set
{
_isRead = value;
OnPropertyChanged(this, "IsRead");
}
}
How can i bind to "IsRead" property of selected item in list?
The current way goes over all Emails in the beginning and doesn't change anything after.
Simply use a DataTrigger with out the need of a converter
<DockPanel >
<TextBox DockPanel.Dock="Top" Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<ListBox x:Name="list" ItemsSource="{Binding EmailsCollection}" SelectedItem="{Binding SelectedItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="{Binding Sender}" Name="SenderLabel" >
<Label.Style>
<Style TargetType="Label">
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRead}" Value="true">
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<!--Style="{StaticResource Sender}"-->
<Label Grid.Row="1" Content="{Binding Subject}" FontSize="12" HorizontalAlignment="Left" />
<Label Grid.Column="1" Content="{Binding Date}" FontSize="12" HorizontalAlignment="Right" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
Update: here the corresponding Model/ViewModel
public class Email:INotifyPropertyChanged
{
private bool _isRead;
public bool IsRead
{
get { return _isRead; }
set
{
_isRead = value;
OnPropertyChanged();
}
}
private String _sender ;
public String Sender
{
get
{
return _sender;
}
set
{
if (_sender == value)
{
return;
}
_sender = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public partial class MainWindow : Window,INotifyPropertyChanged
{
private ObservableCollection<Email> _emailsCollection = new ObservableCollection<Email>(){new Email(){Sender = "FirstSender",IsRead = true},new Email(){Sender = "SecondSender",IsRead = false}};
public ObservableCollection<Email> EmailsCollection
{
get
{
return _emailsCollection;
}
set
{
if (_emailsCollection == value)
{
return;
}
_emailsCollection = value;
OnPropertyChanged();
}
}
private Email _selectedItem=new Email(){IsRead = true};
public Email SelectedItem
{
get
{
return _selectedItem;
}
set
{
_selectedItem = value;
_selectedItem.IsRead = true;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Output
I'm doing a custom control for our company, and I want to define DataTemplate of elements into a ResourceDictionary, for more genericity and skin handling.
My control has a ItemsSource property that contains all collection. I also have a DependencyProperty into my control that specificy the name of the property of current Item to bind on.
Some code :
<DataTemplate x:Key="VEGA_TokenTemplate">
<Border x:Name="Bd" BorderBrush="{StaticResource VEGA_TokenBorderBrush}" BorderThickness="1" Background="{StaticResource VEGA_TokenBackgroundBrush}" Padding="1" Margin="1,5" HorizontalAlignment="Stretch" SnapsToDevicePixels="True">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding WHAT_HERE}" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
<Button Background="Transparent" Content="X" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="10" FontFamily="Berlin Sans FB" Grid.Column="1" Command="{Binding RelativeSource={RelativeSource AncestorType=local:TokenTextBox}, Path=TokenDeleteButtonCommand}"
CommandParameter="{Binding WHAT_HERE}" IsEnabled="True" />
</Grid>
</Border>
</DataTemplate>
In this DataTemplate, I would like to replace the WHAT_HERE tag by the evaluation of my dependency property.
For example, if I set "Email" on my dependency property, I would like the Binding to be like "Path=Email". However, I only have "Email" as litteral into my component. How can I do such a Binding ?
I hope I'm clear in my explainations...
Thank you
I would use Behaviors in this situation or attached properties. I am sure there are other variation of how you can accomplish this. But here is one way to give you an idea
//test interface and test class
public interface IProvidePropertyToBindTo
{
string GetPropertyToBindTo();
}
public class TestChoosingPropertyToBind : IProvidePropertyToBindTo, INotifyPropertyChanged
{
#region Fields
public event PropertyChangedEventHandler PropertyChanged;
private string _emailAddress;
private string _name;
private string _propertyName;
#endregion Fields
#region Properties
public string EmailAddress
{
get { return _emailAddress; }
set
{
if (_emailAddress == value)
return;
_emailAddress = value;
OnPropertyChanged();
}
}
public string Name
{
get { return _name; }
set
{
if (_name == value)
return;
_name = value;
OnPropertyChanged();
}
}
public string PropertyToBindTo
{
set { SetPropertToBindTo(value); }
}
#endregion
#region Methods
public string GetPropertyToBindTo()
{
return _propertyName;
}
public void SetPropertToBindTo(string propertyName)
{
var prop = GetType().GetProperty(propertyName);
if (prop == null)
throw new Exception("Property : "+propertyName+" does not exist in this object {"+this.ToString()+"}.");
_propertyName = propertyName;
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion Methods
}
Test Data
public ObservableCollection<TestChoosingPropertyToBind> Test
{
get
{
return new ObservableCollection<TestChoosingPropertyToBind>(
new List<TestChoosingPropertyToBind>()
{
new TestChoosingPropertyToBind(){EmailAddress = "Test#test.com", PropertyToBindTo = "EmailAddress"},
new TestChoosingPropertyToBind(){Name = "Test", PropertyToBindTo = "Name"}
}
);
}
}
An edited snippet of your data template with the custom behavior
<DataTemplate x:Key="VEGA_TokenTemplate">
<Border x:Name="Bd" BorderBrush="Red" BorderThickness="1" Background="White" Padding="1" Margin="1,5" HorizontalAlignment="Stretch" SnapsToDevicePixels="True">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding WHAT_HERE}" HorizontalAlignment="Stretch" VerticalAlignment="Center" >
<i:Interaction.Behaviors>
<BehaviorLocationNamespace:MyCustomBehavior></BehaviorLocationNamespace:MyCustomBehavior>
</i:Interaction.Behaviors>
</TextBlock>
<Button Background="Transparent"
Content="X"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="10" FontFamily="Berlin Sans FB" Grid.Column="1" IsEnabled="True" />
</Grid>
</Border>
</DataTemplate>
//Items Control usage
<ItemsControl ItemTemplate="{StaticResource VEGA_TokenTemplate}" ItemsSource="{Binding Test}">