I'm using accordion control.
<dxa:AccordionControl.Resources>
<Style TargetType="dxa:AccordionItem">
<Setter Property="Foreground" Value="Orange"/>
<Style.Triggers>
<Trigger Property="IsMouseOverHeader" Value="True">
<Setter Property="Foreground" Value="black"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</dxa:AccordionControl.Resources>
But I don't use it anymore ↑
because I changed the contents of the item dynamically.
Setter setter = new Setter();
Style style2 = new Style();
style2.TargetType = new AccordionItem().GetType();
setter.Property = AccordionItem.ForegroundProperty;
setter.Value = Brushes.Red;
style2.Setters.Add(setter);
ResourceDictionary resourceDictionary = new ResourceDictionary();
resourceDictionary.Add(style2.TargetType, style2);
//Trigger trigger = new Trigger();
//trigger.Property = AccordionItem.IsMouseOverHeaderProperty;
//trigger.Value = true;
accordionControlHistoryMenu.Resources = resourceDictionary;
How Can I express it this xamlcode convert xaml to C# source?
You don't need to store the style in a ResourceDictionary, just assign it directly:
Xaml:
<dxa:AccordionControl.Resources x:Name="myControl">
Code:
myControl.Style = style2;
While this answers your question, it's almost never the correct way to do this. Your styles should be binding to dynamic data that your view model layer is creating.
Related
I have a simple WPF application which displays reddit links in a DataGrid:
Notice however that the link in the DataGridHyperlinkColumn isn't visible when a row is selected, due to the color of the link and the color of the row highlight.
What's a good way to resolve this? Change the link text color? Change the row highlight color?
If possible, please show your suggestion in terms of C# code as opposed to XAML as this application isn't using XAML. Otherwise, a XAML solution is fine; I'll just convert it to C#. :-)
For reference, here's the code used for the Title column:
var event_setter = new EventSetter()
{
Event = Hyperlink.ClickEvent,
Handler = (RoutedEventHandler)((sender, e) =>
{
System.Diagnostics.Process.Start((data_grid.SelectedItem as Link).Url);
})
};
var style = new Style();
style.Setters.Add(event_setter);
var hyperlink_column = new DataGridHyperlinkColumn()
{
Header = "Title",
Binding = new Binding("Title"),
ElementStyle = style,
Width = 600
};
data_grid.Columns.Add(hyperlink_column);
You could add an implicit Hyperlink style to your DataGrid:
const string Xaml = "<Style TargetType=\"Hyperlink\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">" +
"<Style.Triggers>" +
"<DataTrigger Binding=\"{Binding IsSelected, RelativeSource={RelativeSource AncestorType=DataGridCell}}\" Value=\"True\">" +
"<Setter Property=\"Foreground\" Value=\"White\" />" +
"</DataTrigger>" +
"</Style.Triggers>" +
"</Style>";
data_grid.Resources.Add(typeof(Hyperlink), System.Windows.Markup.XamlReader.Parse(Xaml) as Style);
data_grid.Columns.Add(hyperlink_column);
The Selector.IsSelected property of DataGridHyperLink Column can be used and when the selection on particular item changes you can update the style with trigger.
<DataGridHyperlinkColumn.CellStyle>
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="Foreground" Value="Blue"/>
<Style.Triggers>
<Trigger Property="Selector.IsSelected" Value="True">
<Trigger.Setters>
<!--change the value for the property based on your needs-->
<Setter Property="Foreground" Value="Yellow"/>
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
</DataGridHyperlinkColumn.CellStyle>
Pure XAML solution:
<DataGrid>
<DataGrid.Resources>
<Style TargetType="{x:Type Hyperlink}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=DataGridCell}}"
Value="True">
<DataTrigger.Setters>
<Setter Property="Foreground" Value="Yellow"/>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridHyperlinkColumn Width="180"
Header="Url"
Binding="{Binding Path=Uri, Mode=OneWay}" />
</DataGrid.Columns>
</DataGrid>
Here's a version of the answer provided by #mm8 converted from XAML to C#:
var data_trigger = new DataTrigger()
{
Binding = new Binding()
{
Path = new PropertyPath("IsSelected"),
RelativeSource = new RelativeSource() { AncestorType = typeof(DataGridCell) }
},
Value = true
};
data_trigger.Setters.Add(new Setter(ForegroundProperty, new SolidColorBrush(Colors.White)));
var style = new Style(typeof(Hyperlink));
style.Triggers.Add(data_trigger);
data_grid.Resources.Add(typeof(Hyperlink), style);
Here's a version of the answer provided by #mm8 converted from XAML to C# which uses some extension methods to avoid intermediate variables:
data_grid.Resources.Add(
typeof(Hyperlink),
new Style(typeof(Hyperlink))
.AddTrigger(
new DataTrigger()
{
Binding = new Binding()
{
Path = new PropertyPath("IsSelected"),
RelativeSource = new RelativeSource() { AncestorType = typeof(DataGridCell) }
},
Value = true
}
.AddSetter(new Setter(ForegroundProperty, new SolidColorBrush(Colors.White)))));
I am looking for a pure radwindow confirm dialog which only keeps Content and YesNoButton. I didn't find any properties to switch those off. How can I do this? I tried this :
public void ShowConfirm()
{
RadWindow.Confirm(new DialogParameters()
{
Header = "",
Content = new TextBlock()
{
MaxWidth = 200,
Background = new SolidColorBrush(Colors.Red),
Foreground = new SolidColorBrush(Colors.Black),
TextWrapping = TextWrapping.Wrap,
Text = "Test",
FontSize = 24
},
Closed = OnClosed,
WindowStyle = this.Resources["ConfirmDialog"] as Style
});
}
private void OnClosed(object sender, WindowClosedEventArgs e)
{
var result = e.DialogResult;
if (result == true)
{
//
}
}
<Style x:Key="checkWeekDialog" TargetType="telerik:RadWindow">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Width" Value="400"/>
<Setter Property="Background" Value="Yellow"/>
<Setter Property="MinHeight" Value="300"/>
<Setter Property="Icon" Value=""/>
<!--<Setter Property="WindowStartupLocation" Value="CenterOwner"/>-->
<Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>
One way to hide the titlebar of the RadConfirm component is via the VisibleTitlebar property of the RadWindowManager:
Another way is via CSS and this class:
.rwTitlebarControls {
display: none !important;
}
I've been set to maintain a wpf application where there is a listbox for logging purposes.
The items displayed using listbox are of type TextMessage, i.e. the listbox is bound to these text messages via
ObservableCollection<TextMessage> Messages;
listBox.DataContext = Messages;
Messages are then added with something like
Messages.Add(new TextMessage("Test", TypeOfMessage.Headline));
This is the definition of the class TextMessage
public enum TypeOfMessage
{
Normal,
Headline,
Focus,
Important,
Fail,
Success
}
public class TextMessage
{
public TextMessage(string content, TypeOfMessage typeOfMessage)
{
Content = content;
TypeOfMessage = typeOfMessage;
CreationTime = DateTime.Now;
}
public string Content { get; }
public TypeOfMessage TypeOfMessage { get; }
public DateTime CreationTime { get; }
}
The xaml definition for the listbox is something like this:
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="196" Margin="101,77,0,0" VerticalAlignment="Top" Width="256" ItemsSource="{Binding}" SelectionMode="Multiple">
<ListBox.InputBindings>
<KeyBinding
Key="C"
Modifiers="Control"
Command="Copy"
/>
</ListBox.InputBindings>
<ListBox.CommandBindings>
<CommandBinding
Command="Copy"
Executed="DoPerformCopy"
/>
</ListBox.CommandBindings>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="TextToShow" Text="{Binding Content}"></TextBlock>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Normal">
<Setter TargetName="TextToShow" Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Focus">
<Setter TargetName="TextToShow" Property="Foreground" Value="Black"/>
<Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Headline">
<Setter TargetName="TextToShow" Property="Foreground" Value="RoyalBlue"/>
<Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Important">
<Setter TargetName="TextToShow" Property="Foreground" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Fail">
<Setter TargetName="TextToShow" Property="Foreground" Value="Red"/>
<Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
</DataTrigger>
<DataTrigger Binding="{Binding TypeOfMessage}" Value="Success">
<Setter TargetName="TextToShow" Property="Foreground" Value="Green"/>
<Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This works nicely (i.e messages are displayed in the listbox in different font weight and color depending on their type), but now for the question :
Is there any way using BindingExpression or any other means to get the font formatting and coloring from code behind from the xaml definitions ?
The reason is that I want to just have the formatting in one place (just in the xaml as it is right now) but still be able to reuse it when I want to copy the contents (using code behind) including font formatting to the clipboard.
Example:
private void DoPerformCopy()
{
RichTextBox rtb = new RichTextBox();
foreach (TextMessage message in (listBox as ListBox)?.SelectedItems.Cast<TextMessage>().ToList())
{
TextPointer startPos = rtb.CaretPosition;
rtb.AppendText(message.Content);
rtb.Selection.Select(startPos, rtb.CaretPosition.DocumentEnd);
//
// Here it would be very nice to instead having multiple switch statements to get the formatting for the
// TypeOfMessage from the xaml file.
SolidColorBrush scb = new SolidColorBrush(message.TypeOfMessage == TypeOfMessage.Fail ? Colors.Red);
//
rtb.Selection.ApplyPropertyValue(RichTextBox.ForegroundProperty, scb);
}
// Now copy the whole thing to the Clipboard
rtb.Selection.Select(rtb.Document.ContentStart, rtb.Document.ContentEnd);
rtb.Copy();
}
Since I'm new to wpf, I'd really appreciate if someone has a tip for solving this. (I've tried hard to find an solution here at stackoverflow, but so far I've been unsuccessful)
Thanks in advance,
King regards
Magnus
Make a ContentPresenter with Content set to your TextMessage. Set the ContentTemplate to listBox.ItemTemplate and apply the template. It will create the visuals (TextBlock in this case). Then, just parse off the values from the TextBlock.
Also, your RichTextBox selection code wasn't working quite right so I fixed that by just inserting TextRanges to the end of it instead of trying to get the selection right.
private void DoPerformCopy(object sender, EventArgs e)
{
RichTextBox rtb = new RichTextBox();
foreach (TextMessage message in (listBox as ListBox)?.SelectedItems.Cast<TextMessage>().ToList())
{
ContentPresenter cp = new ContentPresenter();
cp.Content = message;
cp.ContentTemplate = listBox.ItemTemplate;
cp.ApplyTemplate();
var tb = VisualTreeHelper.GetChild(cp, 0) as TextBlock;
var fg = tb.Foreground;
var fw = tb.FontWeight;
var tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
tr.Text = message.Content;
tr.ApplyPropertyValue(RichTextBox.ForegroundProperty, fg);
tr.ApplyPropertyValue(RichTextBox.FontWeightProperty, fw);
}
// Now copy the whole thing to the Clipboard
rtb.Selection.Select(rtb.Document.ContentStart, rtb.Document.ContentEnd);
rtb.Copy();
}
I created custom lookless control that define a DependencyProperty of type enum and has a ToggleButton that should set this property via Trigger on IsChecked state. Somehow when I define Setter like this:
<ControlTemplate.Triggers>
<Trigger SourceName="ToggleButton" Property="IsChecked" Value="True">
<Setter Property="ConnectionMode" Value="{x:Static Controls:ConnectionMode.Mode1}" />
</Trigger>
...
</ControlTemplate.Triggers>
then the Visual Studio 2013 designer immediately fails with error:
`ArgumentException: 'Mode1' is not a valid value for the 'MyProject.Controls.CustomControl1.ConnectionMode' property on a Setter.
at System.Windows.Setter.Seal()
at System.Windows.SetterBaseCollection.Seal()
at System.Windows.TriggerBase.ProcessSettersCollection(SetterBaseCollection setters)
at System.Windows.Trigger.Seal()
at System.Windows.TriggerCollection.Seal()
at System.Windows.StyleHelper.SealTemplate(FrameworkTemplate frameworkTemplate, Boolean& isSealed, FrameworkElementFactory templateRoot, TriggerCollection triggers, ResourceDictionary resources, HybridDictionary childIndexFromChildID, FrugalStructList1& childRecordFromChildIndex, FrugalStructList1& triggerSourceRecordFromChildIndex, FrugalStructList1& containerDependents, FrugalStructList1& resourceDependents, ItemStructList`1& eventDependents, HybridDictionary& triggerActions, HybridDictionary& dataTriggerRecordFromBinding, Boolean& hasInstanceValues, EventHandlersStore& eventHandlersStore)
at System.Windows.FrameworkTemplate.Seal()
The DependencyProperty defined as:
namespace MyProject.Controls
{
using ...
public enum ConnectionMode
{
Mode1,
Mode2,
}
public class CustomControl1 : ContentControl
{
public static readonly DependencyProperty ConnectionModeProperty = DependencyProperty.Register("ConnectionMode", typeof(ConnectionMode), typeof(CustomControl1), new PropertyMetadata(default(ConnectionMode), OnCustomConnectionModeChanged));
So my question is: How do I set the DP of type enum from Trigger and still see the control in 'design mode' in Visual Studio ?
Property ConnectionMode is defined at CustomControl1 so it cannot be set from ControlTemplate. Property can be set from CusotmControl1 Style though but not from control template.
Something like this will work:
<Controls:CustomControl1.Style>
<Style TargetType="{x:Type Controls:CustomControl1}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ConnectionMode"
Value="{x:Static Controls:ConnectionMode.Mode1}"/>
</Trigger>
</Style.Triggers>
</Style>
</Controls:CustomControl1.Style>
Pre-Warning sorry WPF new guy here:
I have a DataGrid bound to a DataTable's DefaultView
ResultDataGrid.ItemsSource = resultTable.DefaultView;
I know the column names, and I need to change a column's foreground if another column is 1 (always 0 or 1)
Currently what I have:
private void ResultDataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.Column.Header.ToString() == "columnName")
{
e.Column.CellStyle = FindResource("columnStyle") as Style;
}
}
and in XAML:
<Window.Resources>
<Style TargetType="DataGridCell" x:Key="columnStyle">
<Setter Property="Foreground" Value="Black"/>
<Style.Triggers>
<DataTrigger Binding="{Binding resultTable, Path={StaticResource otherColumnName}}" Value="1">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
Where otherColumnName is set in the constructor
public ResultsCustom(DataTable resultclass, CustomQuery query)
{
// Some other stuff
this.Resources.Add("otherColumnName", COLUMN_NAME);
}
The XAML Style seems to not have the correct path, any help would be appreciated!
I'm not sure about this line of code:
Path={StaticResource otherColumnName}
Are you attempting to compare the property "otherColumnName" of the resultTable to see if this is 1? This wouldn't be a static resource, and you could change your binding to:
Path=otherColumnName