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
Related
There is an Observablecollection Fathers that stores the ID-Firstname-Lastname father. How to make it so that when loading data from the child.lbs file, the ID value that is written in the file under word[4] is selected in the Combobox field? Item values are spelled out using XAML <Combobox "ItemsSource = {Binding Fathers}"/>
That is, so that when the file is loaded, the same values are restored as they were before the shutdown (the so-called Save/Load)
enter image description here
enter image description here
Father.cs
namespace LabelBase.Models
{
public class Father : INotifyPropertyChanged
{
private int _id;
public int FatherID
{
get => _id;
set
{
_id = value;
OnPropertyChanged();
}
}
private string _firstname;
public string Firstname
{
get => _firstname;
set
{
_firstname = value;
OnPropertyChanged();
}
}
private string _secondname;
public string Secondname
{
get => _secondname;
set
{
_secondname = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
Child.cs
namespace LabelBase.Models
{
public class Child : INotifyPropertyChanged
{
private int _id;
public int ChildID
{
get => _id;
set
{
_id = value;
OnPropertyChanged();
}
}
private string _first;
public string Firstname
{
get => _first;
set
{
_first = value;
OnPropertyChanged();
}
}
private string _second;
public string Secondname
{
get => _second;
set
{
_second = value;
OnPropertyChanged();
}
}
private Father _father;
public Father Father
{
get => _father;
set
{
_father = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
child.lbs contents:
13;Ken;Hollow;83
10;Fill;Kenory;93
father.lbs contents:
83;Frank;Malkov
93;Jack;Miles
MainWindow.xaml:
<Grid>
<TabControl>
<TabItem Header="Save">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Save" Margin="100" Height="50" Command="{Binding SaveButton}"/>
<Button Grid.Column="1" Content="Load" Margin="100" Height="50" Command="{Binding LoadButton}"/>
</Grid>
</TabItem>
<TabItem Header="Child">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Margin="5,5,5,50" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Height="25" Margin="5" Text="{Binding ElementName=ChildGrid, Path=Columns[0].Header, StringFormat={}{0}: }" TextAlignment="Right"/>
<TextBlock Grid.Column="0" Grid.Row="1" Height="25" Margin="5" Text="{Binding ElementName=ChildGrid, Path=Columns[1].Header, StringFormat={}{0}: }" TextAlignment="Right"/>
<TextBlock Grid.Column="0" Grid.Row="2" Height="25" Margin="5" Text="{Binding ElementName=ChildGrid, Path=Columns[2].Header, StringFormat={}{0}: }" TextAlignment="Right"/>
<TextBlock Grid.Column="0" Grid.Row="3" Height="25" Margin="5" Text="{Binding ElementName=ChildGrid, Path=Columns[3].Header, StringFormat={}{0}: }" TextAlignment="Right"/>
<TextBox Grid.Column="1" Grid.Row="0" Height="25" Text="{Binding SelectedChildren.ChildID}" Margin="5"/>
<TextBox Grid.Column="1" Grid.Row="1" Height="25" Text="{Binding SelectedChildren.Firstname}" Margin="5"/>
<TextBox Grid.Column="1" Grid.Row="2" Height="25" Text="{Binding SelectedChildren.Secondname}" Margin="5"/>
<ComboBox Grid.Column="1" Grid.Row="3" Height="25" ItemsSource="{Binding Fathers}" SelectedItem="{Binding SelectedChildren.Father}" Margin="5">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="Firstname"/>
<Binding Path="Secondname"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
<DataGrid Name="ChildGrid" Grid.Column="1" Margin="0,10,10,10" AutoGenerateColumns="False" ItemsSource="{Binding Children}" SelectedItem="{Binding SelectedChildren}">
<DataGrid.Columns>
<DataGridTextColumn Width="auto" Header="ID" Binding="{Binding ChildID}"/>
<DataGridTextColumn Width="auto" Header="Firstname" Binding="{Binding Firstname}"/>
<DataGridTextColumn Width="auto" Header="Secondname" Binding="{Binding Secondname}"/>
<DataGridTextColumn Width="auto" Header="Father" Binding="{Binding Father.FatherID}"/>
</DataGrid.Columns>
</DataGrid>
<Button Height="25" Margin="10,0,10,20" Content="Add Child" Command="{Binding AddChildButton}" VerticalAlignment="Bottom"/>
</Grid>
</TabItem>
<TabItem Header="Father">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Margin="5,5,5,50" Grid.Column="0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Height="25" Margin="5" Text="{Binding ElementName=FatherGrid, Path=Columns[0].Header, StringFormat={}{0}: }" TextAlignment="Right"/>
<TextBlock Grid.Column="0" Grid.Row="1" Height="25" Margin="5" Text="{Binding ElementName=FatherGrid, Path=Columns[1].Header, StringFormat={}{0}: }" TextAlignment="Right"/>
<TextBlock Grid.Column="0" Grid.Row="2" Height="25" Margin="5" Text="{Binding ElementName=FatherGrid, Path=Columns[2].Header, StringFormat={}{0}: }" TextAlignment="Right"/>
<TextBox Grid.Column="1" Grid.Row="0" Height="25" Text="{Binding SelectedFathers.FatherID}" Margin="5"/>
<TextBox Grid.Column="1" Grid.Row="1" Height="25" Text="{Binding SelectedFathers.Firstname}" Margin="5"/>
<TextBox Grid.Column="1" Grid.Row="2" Height="25" Text="{Binding SelectedFathers.Secondname}" Margin="5"/>
</Grid>
<DataGrid Name="FatherGrid" Grid.Column="1" Margin="0,10,10,10" AutoGenerateColumns="False" ItemsSource="{Binding Fathers}" SelectedItem="{Binding SelectedFathers}">
<DataGrid.Columns>
<DataGridTextColumn Width="auto" Header="ID" Binding="{Binding FatherID}"/>
<DataGridTextColumn Width="auto" Header="Firstname" Binding="{Binding Firstname}"/>
<DataGridTextColumn Width="auto" Header="Secondname" Binding="{Binding Secondname}"/>
</DataGrid.Columns>
</DataGrid>
<Button Height="25" Margin="10,0,10,20" Content="Add Father" Command="{Binding AddFatherButton}" VerticalAlignment="Bottom"/>
</Grid>
</TabItem>
</TabControl>
</Grid>
ContextVIew.cs:
using LabelBase.Models;
namespace LabelBase
{
public class ContextView : INotifyPropertyChanged
{
public ObservableCollection<Father> Fathers { get; }
public ObservableCollection<Child> Children { get; }
private Father _selectedFather;
public Father SelectedFathers
{
get => _selectedFather;
set
{
_selectedFather = value;
OnPropertyChanged();
}
}
private RelayCommand _addFatherButton;
public RelayCommand AddFatherButton
{
get
{
return _addFatherButton ?? (_addFatherButton = new RelayCommand(obj =>
{
Father f = new Father();
Random r = new Random();
f.FatherID = r.Next(99);
Fathers.Insert(Fathers.Count, f);
SelectedFathers = f;
}));
}
}
private Child _selectedChild;
public Child SelectedChildren
{
get => _selectedChild;
set
{
_selectedChild = value;
OnPropertyChanged();
}
}
private RelayCommand _addChildButton;
public RelayCommand AddChildButton
{
get
{
return _addChildButton ?? (_addChildButton = new RelayCommand(obj =>
{
Child c = new Child();
Random r = new Random();
c.ChildID = r.Next(99);
Children.Insert(Children.Count, c);
SelectedChildren = c;
}));
}
}
private RelayCommand _save;
public RelayCommand SaveButton
{
get
{
return _save ?? (_save = new RelayCommand(obj =>
{
StreamWriter swChild = new StreamWriter($"{AppDomain.CurrentDomain.BaseDirectory}/save/child.lbs", false);
StreamWriter swFather = new StreamWriter($"{AppDomain.CurrentDomain.BaseDirectory}/save/father.lbs", false);
foreach(Child item in Children)
{
string sandwich = $"{item.ChildID};{item.Firstname};{item.Secondname};{item.Father.FatherID}";
swChild.WriteLine(sandwich);
}
swChild.Close();
foreach (Father item in Fathers)
{
string sandwich = $"{item.FatherID};{item.Firstname};{item.Secondname}";
swFather.WriteLine(sandwich);
}
swFather.Close();
MessageBox.Show("Complete");
}));
}
}
private RelayCommand _load;
public RelayCommand LoadButton
{
get
{
return _load ?? (_load = new RelayCommand(obj =>
{
StreamReader srChild = new StreamReader($"{AppDomain.CurrentDomain.BaseDirectory}/save/child.lbs", false);
StreamReader srFather = new StreamReader($"{AppDomain.CurrentDomain.BaseDirectory}/save/father.lbs", false);
string lineChild, lineFather;
while((lineFather = srFather.ReadLine()) != null)
{
string[] word = lineFather.Split(';');
Father f = new Father();
f.FatherID = int.Parse(word[0]);
f.Firstname = word[1];
f.Secondname = word[2];
Fathers.Insert(Fathers.Count, f);
}
while((lineChild = srChild.ReadLine()) != null)
{
string[] word = lineChild.Split(';');
Child c = new Child();
c.ChildID = int.Parse(word[0]);
c.Firstname = word[1];
c.Secondname = word[2];
//c.Father.FatherID = int.Parse(word[3]);
Children.Insert(Children.Count, c);
}
srChild.Close();
MessageBox.Show("Complete");
}));
}
}
public ContextView(){
Fathers = new ObservableCollection<Father>();
Children = new ObservableCollection<Child>();
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
}
There is a Project: https://github.com/RodKingroo/FatherChild
Who will help, thanks :)
Thanks, #BionicCode 4 ur help
Answer ContextWiew.cs:
using (StreamReader srChild = new StreamReader($"{AppDomain.CurrentDomain.BaseDirectory}/save/child.lbs")) {
lineChild = srChild.ReadLine();
while ((lineChild = srChild.ReadLine()) != null)
{
string[] word = lineChild.Split(';');
Child c = new Child();
c.ChildID = int.Parse(word[0]);
c.Firstname = word[1];
p.Secondname = word[2];
foreach (Father item in Father)
{
if (item.FatherID == int.Parse(word[5])) p.Father = item;
}
Children.Add(c);
SelectedChildren = c;
}
srChild.Close();
}
I have an annoying bug that I can't seem to figure out and it is driving me crazy. I have a window with a listbox in it and when an item is selected an new window is opened using mvvm light which displays different details, the problem is when I click on the item in my listbox (BrowseGamesView) the new window that opens (GameDetailsView) does not show the background image unless I click back to the BrowseGamesView. I'm calling to an api and using a converter to build the url for the image. I need the image to show when the new window opens.
GameDetailsView
Where I need the background image to show when the window opens.
<Window.Resources>
<vm:GameDetailsViewModel x:Key="vm"/>
<converters:StringToBackgroundImageConverter x:Key="stringToBackgroundImageConverter"/>
<converters:StringToImageConverter x:Key="stringToImageConverter"/>
</Window.Resources>
<Grid DataContext="{StaticResource vm}">
<Grid.Background>
<ImageBrush ImageSource="{Binding Game.ScreenshotBackground, Converter={StaticResource stringToBackgroundImageConverter}}"/>
</Grid.Background>
</Grid>
BrowseGamesView
Where the listbox is held.
<ListBox ItemsSource="{Binding Games}"
ItemContainerStyle="{DynamicResource ListBoxItemStyle1}"
SelectedItem="{Binding SelectedGame}"
Width="480"
Height="500"
Grid.Row="4">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="{Binding cover.image_id, Converter={StaticResource stringToImage}}"
Stretch="Fill"
Width="100"
Height="130"/>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="310"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding name}"
Foreground="White"
FontWeight="Bold"
FontSize="16"
Margin="15 2 0 0"
TextWrapping="Wrap"/>
<TextBlock Text="{Binding aggregated_rating, StringFormat={}{0:F0}, Converter={StaticResource nullRatingConverter}}"
Grid.Column="1"
Foreground="{Binding AggregatedRatingColor}"
FontWeight="Bold"
FontSize="16"
HorizontalAlignment="Center"/>
</Grid>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding DeveloperCompanies}"
Margin="15 2 0 0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="commaTextBlock"
Text=", "
Foreground="White"/>
<TextBlock Text="{Binding company.name}"
Foreground="White"
TextWrapping="Wrap"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter Property="Visibility" TargetName="commaTextBlock" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Grid.Row="2"
VerticalAlignment="Bottom"
Margin="0 0 0 4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Release Date:"
Foreground="White"
Margin="15 20 0 0"/>
<TextBlock Text="{Binding first_release_date, Converter={StaticResource unixTimestampToDateTimeConverter}}"
Foreground="White"
Margin="10 20 0 0"
Grid.Column="1"/>
</Grid>
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
GameDetailsViewModel
public class GameDetailsViewModel : INotifyPropertyChanged
{
private Game game;
public Game Game
{
get { return game; }
set
{
game = value;
OnPropertyChanged("Game");
}
}
public GameDetailsViewModel()
{
Messenger.Default.Register<Game>(this, NotifyMe);
}
public void NotifyMe(Game sentGame)
{
Game = sentGame;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
BrowseGamesViewModel
public class BrowseGamesViewModel : ViewModelBase, INotifyPropertyChanged
{
private string query;
private Game selectedGame;
private int gamesCount;
private Game game;
public RelayCommand ShowGameDetailsViewCommand { private set; get; }
public string Query
{
get { return query; }
set
{
query = value;
OnPropertyChanged("Query");
}
}
public Game Game
{
get { return game; }
set
{
game = value;
OnPropertyChanged("Game");
}
}
public Game SelectedGame
{
get { return selectedGame; }
set
{
selectedGame = value;
OnPropertyChanged("SelectedGame");
GetGameDetails();
ShowGameDetailsViewCommandExecute();
}
}
public ObservableCollection<Game> Games { get; set; }
public int GamesCount
{
get { return gamesCount; }
set
{
gamesCount = value;
OnPropertyChanged("GamesCount");
}
}
public SearchGamesCommand SearchGamesCommand { get; set; }
public BrowseGamesViewModel()
{
Games = new ObservableCollection<Game>();
SearchGamesCommand = new SearchGamesCommand(this);
ShowGameDetailsViewCommand = new RelayCommand(ShowGameDetailsViewCommandExecute);
}
public void ShowGameDetailsViewCommandExecute()
{
Messenger.Default.Send(new NotificationMessage("ShowGameDetailsView"));
}
private async void GetGameDetails()
{
Game = await IGDBHelper.GetGameInformation(SelectedGame.id);
Messenger.Default.Send(Game);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
BrowseGamesView Code Behind
public partial class BrowseGamesView : Window
{
public BrowseGamesView()
{
InitializeComponent();
Messenger.Default.Register<NotificationMessage>(this, NotificationMessageReceived);
}
private void NotificationMessageReceived(NotificationMessage msg)
{
if (msg.Notification == "ShowGameDetailsView")
{
var view = new GameDetailsView();
view.Show();
}
}
}
<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
In XAML I have a list view:
<UserControl x:Class="HspSetup.View.UserInputData"
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:HspSetup.View"
xmlns:viewModel="clr-namespace:HspSetup.ViewModel"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:Behaviours="clr-namespace:HspSetup.Behaviours"
mc:Ignorable="d"
Height="Auto" Width="Auto">
<UserControl.Resources>
<viewModel:UserInputDataViewModel x:Key="ViewModel"/>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="0.1*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<TextBlock Background="Coral" Height="50"
VerticalAlignment="Center" TextAlignment="Center"
Grid.Row="0" Grid.ColumnSpan="3">
<TextBlock.Text>Some More Data</TextBlock.Text>
<TextBlock.FontFamily>Segoe UI</TextBlock.FontFamily>
<TextBlock.Foreground>White</TextBlock.Foreground>
<TextBlock.FontSize>30</TextBlock.FontSize>
</TextBlock>
<ListView Grid.Row="2" Width="Auto"
Behaviours:GridViewColumnResize.Enabled="True"
Height="Auto" Name="OrderNumberListView"
IsSynchronizedWithCurrentItem="True" Grid.Column="1"
DataContext="{Binding Source={StaticResource ViewModel}}"
ItemsSource="{Binding ConfigObjects}" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="Behaviours:LostFocus.LostFocusCommand"
Value="{Binding Path=LostFocusCommand, Source={StaticResource ViewModel}}"/>
<Setter Property="Behaviours:LostFocus.CommandParem"
Value="{Binding}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="Order Name"
Behaviours:GridViewColumnResize.Width="*">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding OrderNumber, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource flatTextBox}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Type Name"
Behaviours:GridViewColumnResize.Width="*">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding TypeName, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource flatTextBox}">
</TextBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Behaviours:GridViewColumnResize.Width="*" >
<GridViewColumn.HeaderTemplate>
<DataTemplate>
<Button Content="Add"
Command="{Binding AddConfigObjectCommand, Mode=OneWay, Source={StaticResource ViewModel}}"/>
</DataTemplate>
</GridViewColumn.HeaderTemplate>
<GridViewColumnHeader HorizontalContentAlignment="Stretch"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Name="RemoveButton"
Content="Remove"
Command="{Binding RemoveConfigObjectCommand, Mode=OneWay, Source={StaticResource ViewModel}}" CommandParameter="{Binding}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</UserControl>
The Corresponding UI looks like this:
On Click of an Add button I add an Empty row as follows :
I Enter text into the text boxes.
The change made to the listview by entering text in the textbox is not updating the observableCollection to which the textboxes are bound.
The class of the observable collection is as below :
class UserInputDataViewModel: BaseViewModel
{
private ObservableCollection<ConfigObject> _configObjects;
public ObservableCollection<ConfigObject> ConfigObjects
{
get { return _configObjects; }
set
{
_configObjects = value;
OnPropertyChanged("ConfigObjects");
}
}
private ICommand _addConfigObject;
public ICommand AddConfigObjectCommand
{
get
{
if (_addConfigObject == null)
{
_addConfigObject = new RelayCommand(
p => AddConfigObject(),
p => CanAddConfigObject);
}
return _addConfigObject;
}
}
private void AddConfigObject()
{
ConfigObjects.Add(new ConfigObject() { OrderNumber = "", TypeName = "" });
OnPropertyChanged("ConfigObjects");
}
private ICommand _removeConfigObject;
public ICommand RemoveConfigObjectCommand
{
get
{
if (_removeConfigObject == null)
{
_removeConfigObject = new RelayCommand(
p => RemoveConfigObject((ConfigObject)p),
p => CanRemoveConfigObject);
}
return _removeConfigObject;
}
}
private void RemoveConfigObject(ConfigObject configObject)
{
ConfigObjects.Remove(configObject);
OnPropertyChanged("ConfigObjects");
}
bool CanAddConfigObject
{
get { return true; }
}
bool CanRemoveConfigObject
{
get { return true; }
}
}
class BaseViewModel:INotifyPropertyChanged
{
/// <summary>
/// Name of the property that changed
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Send the notification to the property that change
/// </summary>
/// <param name="pPropertyName">name of the property</param>
protected virtual void OnPropertyChanged(string pPropertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this,
new PropertyChangedEventArgs(pPropertyName));
}
}
}
internal class ConfigObject : INotifyPropertyChanged
{
private string _orderNumber;
public string OrderNumber
{
get { return _orderNumber; }
set { _orderNumber = value; OnPropertyChanged("OrderNumber"); }
}
private string _typeName;
public string TypeName
{
get { return _typeName; }
set { _typeName = value; OnPropertyChanged("TypeName"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string paramname)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(paramname));
}
}
By editing the text in the textboxes you do not change the ObservableCollection but you change one of the objects inside the collection. The collection is not aware of changing the internal(!) state of one the objects in it. Those changes can be captured by the PropertyChanged event of your ConfigObject class.
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}">