I have a WPF app and I want to add an item with HorizontalAlignment = Left and then other with HorizontalAlignment = right, like a chat in Whatsapp, but all the text in the listbox have horizontal alignment on the right, How can I use different horizontal alignment in the same listbox.
This is my XAML code:
<ListBox x:Name="ListBoxChat" HorizontalAlignment="Stretch" Height="366" VerticalAlignment="Top" Width="270" Margin="2,44,0,0" Padding="2"/>
<TextBlock Foreground="Transparent" Name="TextB" Margin="2,-5,2,-3"></TextBlock>
and this is the C# code behind:
ListBoxChat.HorizontalAlignment = HorizontalAlignment.Left;
ListBoxChat.Items.Add("How are you ?");
ListBoxChat.HorizontalAlignment = HorizontalAlignment.Right;
ListBoxChat.Items.Add("Fine!!!");
Thank you!
You can create a single StackPanel to carry the ListView. Like this,
<StackPanel>
<ListView x:Name="chatList" Width="value" />
</StackPanel>
You don't really need the StackPanel, I just used it!
Now on the CSharp code, you can handle the events of the User or the Network. I won't go in the Depth of the process, but an example of that would be
void addItem (object sender, EventArgs e) {
// first create the new item!
ListViewItem item = new ListViewItem();
// add the properties..
item.Content = "Hi, my name is Slim Shady!";
if(messageBy == "user") {
// if message is by user, align it to right
item.HorizontalAlignment = HorizontalAlignment.Left;
} else {
// if message is by network (friend), align it to left
item.HorizontalAlignment = HorizontalAlignment.Right;
}
// now add the item to the listbox
chatList.Items.Add(item); // done! :-)
}
You can execute this code, each time there is new item to be appened! But you really need to make sure that the conditions are checked. Because using the Condition, you can change the color of the item too, like in WhatsApp, you can do other stuff too. It totally depends on the Condition, and the Way you use it.
Good luck!
You can achieve this by applying the style on your ListBoxItem and using AlternationCount and AlternationIndex as shown below:
<ListBox x:Name="ListBoxChat" HorizontalAlignment="Stretch" Height="366" VerticalAlignment="Top" Width="270" Margin="2,44,0,0" Padding="2"
AlternationCount="2">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="HorizontalContentAlignment" Value="Left"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Self}}" Value="1">
<Setter Property="HorizontalContentAlignment" Value="Right"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
Related
For a project I need to set buttons foreground color depending on values returned from a database.
F.e. if the value == 1 the foreground needs to be green.
when the value == 0 it needs to have its original gray color.
I have the following design for my buttons in my wpf DataGrid
<DataGrid.Columns>
<DataGridTemplateColumn Width="40">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="FavoriteButton" ... Foreground="#454545" Click="Button_Click">ButtonTextHere</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
Other columns are automatically generated by the DataGrid's ItemsSource.
I tried to declare a public button in the behind code of my DataGrid but could not reference the buttons name "FavoriteButton"
This is what I was trying
public partial class DataGridMain : UserControl
{
public Button btn;
public DataGridMain()
{
InitializeComponent();
btn = FavoriteButton
}
}
I already have this code to loop through my DataGrid
foreach (System.Data.DataRowView dr in MainGrid.ItemsSource)
{
if (dr[9].ToString() == "1")
{
// here should come the action to actually
// change the foreground color of the Button.
}
else
{
// Set original color
}
}
If anyone knows a good way to handle this, I would be thankful if you shared your knowledge!
Simply add a DataTrigger to your Button like this:
<DataGrid.Columns>
<DataGridTemplateColumn Width="40">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="FavoriteButton" Click="FavoriteButton_Click">ButtonTextHere
<Button.Style>
<Style TargetType="Button">
<Setter Property="Foreground" Value="#454545"/>
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="true">
<Setter Property="Foreground" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
Moreover, it would nice to map your colors to different StaticResourceshared to other UI components in order to let you changed it quickly painless if needed.
Bind the foregroundcolor in your XAML to another color property, so you are able to change it in your code:
<Button x:Name="color" Foreground="Green" Visibility="Hidden"/>
put this in your FavoriteButton:
Foreground="{Binding ElementName=color, Path=Foreground, UpdateSourceTrigger=PropertyChanged}"
Now you can change the color like this:
color.Foreground = Brushes.Gray;
I admit, that this is not a professional way, but it should work
I have a problem with my Datagrid. (MVVM)
I have a textbox that sets the SelectedIndex depending on where I click in the text. This works!
But the table in the datagrid can get quite long, and if the line that I want to highlight is not visible when clicking in the textbox it does not mark the line as selected.
So my question is if it is possible to select the line even though it is not visible? So if i scroll down that it shows the line as selected.
Or what would probably be better just jump to this line if not visible. (Set to top row or scroll to it automatically). Is this possible, if yes how?
Here is the xaml of the datagrid :
<DataGrid Name="dtgDecodedMsg"
CanUserSortColumns="False"
CanUserAddRows="False"
CanUserReorderColumns="False"
HeadersVisibility="Column"
IsTabStop="False"
ClipboardCopyMode="IncludeHeader"
SelectedIndex="{Binding DecodeSelectedGridIdx, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path=MsgTypGridLineListVar, UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False"
Margin="10,111,10,0">
This is how I highlight the Rows : (The rows don't get highlighted even if I set index on DecodeSelectedGridIdx and call the OnPropertychanged)
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="Aqua"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
</Style.Triggers>
This is how I set the index :
public int DecodeSelectedGridIdx
{
set
{
this.m_decodeSelectedGridIdx = value;
...
OnPropertyChanged("DecodeSelectedGridIdx");
}
}
Thank you for your help !
You could handle the SelectionChanged event for the DataGrid in the view and call the ScrollIntoView method:
private void dtgDecodedMsg_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
dtgDecodedMsg.ScrollIntoView(dtgDecodedMsg.SelectedItem);
}
XAML:
<DataGrid Name="dtgDecodedMsg" ... SelectionChanged="dtgDecodedMsg_SelectionChanged">
...
You could wrap this functionality in a behaviour if you intend to use it in several views: https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF
I have a method that is supposed to color the background of a textbox that is on focus(Enter)
private void onEnter_ColourChange(object sender, EventArgs e)
{
this.BackColor = Color.White;
}
This doesn't work, however. I checked this answer, but I just got a NullReferenceException.
Essentially, I would like to color multiple textboxes when the textbox is in focus, with one method. Is there a way to do this?
First of all: TextBox has only the property Background and not BackColor!
If you want to change the color of the focused TextBox, a simple way is, to use a Style with a Trigger.
<Window.Resources>
<Style TargetType="TextBox" x:Key="TextBoxFocusBackgroundStyle" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="true" >
<Setter Property="Background" Value="Brown" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
As you can see, the Trigger watches on the property IsFocused. If the TextBox got the Focus (so IsFocused changes to true), the Background will be brown.
To use this Style:
<StackPanel>
<TextBox Text="Peter" Style="{StaticResource TextBoxFocusBackgroundStyle}"/>
<TextBox Text="Laszlo" Style="{StaticResource TextBoxFocusBackgroundStyle}"/>
<TextBox Text="Julia" Style="{StaticResource TextBoxFocusBackgroundStyle}"/>
<TextBox Text="Romeo" Style="{StaticResource TextBoxFocusBackgroundStyle}"/>
</StackPanel>
If you already has a Style for the TextBoxes you should use that Style in the BasedOn attribute.
I have this content dialog box defined inside my xaml:
<ContentDialog x:Name="AlertMessage" Background="#363636" IsSecondaryButtonEnabled="True" SecondaryButtonText="Cancel" IsPrimaryButtonEnabled="True" PrimaryButtonText="Ok" >
<ContentDialog.Content>
<StackPanel Name="rootStackPanel" Height="Auto" >
<StackPanel Margin="0">
<StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock x:Name="HeadingText" x:FieldModifier="public" Style="{StaticResource ApplicationMessageBoxHeadingStyle}" Text="Alert" />
<Image Margin="10,05,0,0" Source="/Assets/Images/alert.png" Width="35"></Image>
</StackPanel>
<TextBlock x:FieldModifier="public" x:Name="ContentText" Style="{StaticResource ApplicationMessageBoxErrorStyle}" Text="Are you sure you want to log off ?" />
</StackPanel>
</StackPanel>
</ContentDialog.Content>
</ContentDialog>
And I'm calling it like this:
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
MessageBox();
}
private async void MessageBox()
{
ContentDialogResult LogoutDialog = await AlertMessage.ShowAsync();
if (LogoutDialog == ContentDialogResult.Primary)
{
this.Frame.Navigate(typeof(MainPage));
}
else
{
// User pressed Cancel or the back arrow.
// Terms of use were not accepted.
}
}
Problem: is that my app have a style for all the buttons in my applications. And I want to apply same styles to the primary and secondary buttons of that dialog box too. And I am unable to figure out how to Achieve this. Is it possible to apply styles to these buttons?
I used this code to change Button color on my UWP app.
var cd = new ContentDialog();
cd.Content = "Remove file ?";
cd.Title = "Remove file";
cd.PrimaryButtonText = "OK";
cd.SecondaryButtonText = "Cancel";
var bst = new Windows.UI.Xaml.Style(typeof(Button));
bst.Setters.Add(new Setter(Button.BackgroundProperty, Colors.Red));
bst.Setters.Add(new Setter(Button.ForegroundProperty, Colors.White));
cd.PrimaryButtonStyle = bst;
var ress = await cd.ShowAsync();
You can indirectly customize the buttons.
The ContentDialog's buttons use the "default" style for the target type "Button". You can overwrite the ContentDialog Style of the SDK and add a different Button Style in the Setter of the Template. This button style will just be valid in the scope of the ContentDialog control.
In this example the new button style needs to be put in the first border element (x:Name="Container")
<Border.Resources>
<Style TargetType="Button" BasedOn="{StaticResource YourNormalButtonStyle}">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="Foreground" Value="Red"/>
</Style>
</Border.Resources>
If you want to change the ContendDialog PrimaryButtonSettings you need inside ContenDialog.Resources just to set a Style that you are targeting Buttons and the Setter of With Property="" and Value="" and that should fix below is one example.
Converter={StaticResource StringEmptyToBoolConverter}}"
<ContentDialog.Resources>
<converters:StringEmptyToBoolConverter x:Key="StringEmptyToBoolConverter"/>
<Style TargetType="Button">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FontSize" Value="13.6"/>
<Setter Property="Width" Value="Auto"/>
</Style>
</ContentDialog.Resources>
<WebView Height="400" Width="500" DefaultBackgroundColor="Transparent" Source="{Binding State.GuideUri}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="RulesWebView"/>
The ContentDialog buttons aren't customizable, but you can leave the ContentDialog's primary and secondary buttons unset and add your own buttons within the template.
I'm making a MVVM WPF application, in this application I have a ListBox with my own Privilege Items.
After ages I finally found a solution how to get selection synchronized with my ViewModel. (You also need to implement IEquatable in your item class)
Problem
Now i want to style the ListBoxItems as CheckBoxes, there are many solutions for this problem, but none that really fits my needs.
So i came up with this solution, because I can apply this style only to the ListBoxes I need, and I don't have to worry about the DisplayMemberPath or that the Items were styled as CheckBox and ListBoxItems.
View:
<ListBox Grid.Row="5" Grid.Column="1"
ItemsSource="{Binding Privileges}"
BehavExt:SelectedItems.Items="{Binding SelectedPrivileges}"
SelectionMode="Multiple"
DisplayMemberPath="Name"
Style="{StaticResource CheckBoxListBox}"/>
Style:
<Style x:Key="CheckBoxListBox"
TargetType="{x:Type ListBox}"
BasedOn="{StaticResource MetroListBox}">
<Setter Property="Margin" Value="5" />
<Setter Property="ItemContainerStyle"
Value="{DynamicResource CheckBoxListBoxItem}" />
</Style>
<Style x:Key="CheckBoxListBoxItem"
TargetType="{x:Type ListBoxItem}"
BasedOn="{StaticResource MetroListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<CheckBox IsChecked="{TemplateBinding Property=IsSelected}">
<ContentPresenter />
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ViewModel:
private ObservableCollection<Privilege> _privileges;
public ObservableCollection<Privilege> Privileges
{
get { return _privileges; }
set {
_privileges = value;
RaisePropertyChanged(() => Privileges);
}
}
private ObservableCollection<Privilege> _selectedPrivileges;
public ObservableCollection<Privilege> SelectedPrivileges
{
get { return _selectedPrivileges; }
set
{
_selectedPrivileges = value;
RaisePropertyChanged(() => SelectedPrivileges);
}
}
The Problem is this line:
IsChecked="{TemplateBinding Property=IsSelected}"
It works fine, but only in one direction. When add a item to my SelectedPrivileges in the code it will be displayed as checked, but when I check this item in the GUI it won't do anything. (Without the CheckBox style it works, so it is because a TemplateBinding only works in one direction)
How do I get this to work? I though about something like a trigger, but I have no clue how to accomplish this.
I believe what you're looking for is actually pretty straightforward. You need to change the binding mode of the IsChecked property's binding, as follows:
{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected, Mode=TwoWay}
That should do it.
This and basically any other WPF binding tips can be found on this excellent cheat sheet.