I would like to programmatically change content of button via style change. I created a style, added setter for Button.ContentProperty, set new style to button, but content was not changed.
I know that I can set button content directly, but now I would like to know why this does not work:
Style aStyle = new Style();
Setter bSetter = new Setter();
bSetter.Property = Button.ContentProperty;
bSetter.Value = "Some Text";
aStyle.Setters.Add(bSetter);
aButton.Style = aStyle;
XAML:
<Button x:Name="aButton" Style="{x:Null}" Click="Button_Click" />
I could change appearance of a button this way, but I couldn't change content. Btw, I found example in MCTS book on WPF.
Any idea?
This code works for me as is. Are you sure you're not changing Content from other place? you can try
var source = DependencyPropertyHelper.GetValueSource(aButton, ContentControl.ContentProperty);
... to figure it out. I prefer to use WPF snoop for this.
Well, today I found out that there is order of precedence when setting property values in WPF. There is number of mechanisms for setting property value and property value depends on how it was set, not when it was set.
Setting property value in XAML or through code will always precede values set by Style (and templates and triggers). That is, when property value is set in XAML or through code, it cannot be overridden by setting style.
To be able to change property value with mechanism of lower precedence, value must be cleared with DependencyObject.ClearValue method.
In my code example above there was one other method that set Button.Content property in code, so style could not change it any more. Solution for this is to add ClearValue method:
Style aStyle = new Style();
Setter bSetter = new Setter();
bSetter.Property = Button.ContentProperty;
bSetter.Value = "Some Text";
aStyle.Setters.Add(bSetter);
aButton.ClearValue(ContentProperty); // <<-- Added this line to clear button content
aButton.Style = aStyle;
Related
I have created a ListView with a GridView in code.
ListView gridList = new ListView();
GridView gridListView = new GridView ();
gridList.View = gridListView;
Now, I define a GridViewColumn, set the header, width and bindingPath. All good and the data shows up.
GridViewColumn listColumn = new GridViewColumn();
listColumn.Header = "Some Header";
listColumn.Width = 100.0;
listColumn.DisplayMemeberBinding = new Binding("Name");
gridListView.Columns.Add(listColumn);
But there are no borders/gridlines shown on display of this ListView. How can I add borders through code?
Someone described my exact problem here but no good solution mentioned
http://social.msdn.microsoft.com/Forums/en-US/fa4fa8e0-81fe-487a-8763-590062d29c06/wpf-listview-gridview-row-border?forum=wpf
The logic in WPF programming is totally different from what you've done in winforms. Everything related to UI should always be set up using XAML (as much as possible). The WPF library itself has many parts desgined mainly for use in XAML although there is always an equivalent codebehind. However that's when using codebehind may be awkward and non-intuitive (as well as straight-forward).
I understand that you want something like the ListView Grid in Winforms. In WPF that can be achieved easily if you use XAML code. Even in code behind, you can always build a Style or Template from XAML string (with the help of XamlReader). This approach is good for complex scenario but in this case I have another approach (don't use the XAML parser at all). This trick does render the grid which is good enough (and at best it can do for the trade-off of simplicity):
//we need an instance of Style to set to ListView.ItemContainerStyle
var style = new Style(typeof(ListViewItem));
//set the bottom border thickness to 1
var setter = new Setter(Control.BorderThickness, new Thickness(0,0,0,1));
style.Setters.Add(setter);
//set the border brush
var borderBrush = new LinearGradientBrush { StartPoint = new Point(0,0),
EndPoint = new Point(1,0)};
var gradStop = new GradientStop(Colors.Transparent, 0.001);
borderBrush.GradientStops.Add(gradStop);
gradStop = new GradientStop(Colors.Green, 0.001);
borderBrush.GradientStops.Add(gradStop);
gradStop = new GradientStop(Colors.Green, 0.999);
borderBrush.GradientStops.Add(gradStop);
gradStop = new GradientStop(Colors.Transparent, 0.999);
borderBrush.GradientStops.Add(gradStop);
setter = new Setter(Control.BorderBrush, borderBrush);
style.Setters.Add(setter);
yourListView.ItemContainerStyle = style;
Note that the default inner Border of each ListViewItem has a hard-coded CornerRadius of about 2, so by setting just the bottom BorderBrush to a solid brush such as Brushes.Green will show a little upwards curly line at the 2 ends of the bottom border. You can try it yourself. If this result is acceptable, the code can be shorter and simpler (because you don't have to define the GradientBrush to cut-off the 2 curly ends) like this:
setter = new Setter(Control.BorderBrush, Brushes.Green);
style.Setters.Add(setter);
If the behavior is still not what you want. You should try the approach I mentioned about using XamlReader to parse a XAML string and get an instance of whatever you want in codebehind. (you can search it yourself, it's easy to have some result).
I suggest you see this link, it contains a dynamic GridView created in code-behind that can be useful for your specific case. For the code sample that you provided, you didn't add ShowGridLines property.
When setting the Text property of a WPF TextBox control, other properties that should also change (as a side effect) do not change. In particular, I would like to check the value of the ExtentWidth property after setting Text, but it does not change. I've tried calling UpdateLayout() to no avail. In Windows.Forms, I would call DoEvents().
OK, here's some code. I put this in the Window_Loaded() event handler. The problem is that textBox.ExtentWidth doesn't change when textBox.Text changes. That doesn't really surprise me. I figure I need to call something like textBox.UpdateLayout() to make it recalculate ExtentWidth, but that didn't help. ExtentWidth does vary depending on what I initialize textBox.Text to in the Window's constructor, but that doesn't help me. I need to set several different Text values and get the corresponding ExtentWidth for each.
string initText = textBox.Text; // "textBox"
double extentWidth = textBox.ExtentWidth; // 39.3
textBox.Text = "short text";
extentWidth = textBox.ExtentWidth; // 39.3
textBox.Text = "Long enough to make a difference, eh?";
extentWidth = textBox.ExtentWidth; // 39.3
I found a solution to the specific problem of getting TextBox.ExtentWidth to change after setting Text. Setting Text will raise the LayoutUpdated event, and you can get the new value of ExtentWidth in a handler for LayoutUpdated.
I used this fact to create a subclass of WPF TextBox that displays an ellipsis when the text is too long for the visible area. I wrote a CodeProject article about it here.
I have a group of borders that make up a small map. Ideally I'd like to be able to bind the border's background property to a property in a custom list and when that property changes it changes the background.
The tricky thing is, I have to do this in code behind.
Use the FrameworkElement.SetBinding method:
myBorder.SetBinding(Border.BackgroundProperty, "CurrentBackground");
or, if you need sources and converters and things:
myBorder.SetBinding(Border.BackgroundProperty,
new Binding(somePath) {
Source = something,
Converter = new WonderConverter()
// etc.
});
I have a application where user can set the datagrid header background color in runtime. How can I do this? I tried the same through the following code but it is throwing exception.I have used binding and but it's not working.
var style = this.Resources["DataGridHeaderStyle"] as Style;
style.Setters.SetValue(DataGridColumnHeader.BackgroundProperty, "Red");
Without further details (such as the exception you are getting) its difficult to see why you are getting an exception. I suspect that the style variable has a null reference.
I also suspect that the reason its null is that the "DataGridHeaderStyle" doesn't exist in the resource dictionary of the this object, which I would guess is a UserControl. In order to acquire the Style you need to do this look up on the actual FrameworkElement object that holds the Style in its Resources property. (Note programmatic access to the resources does not cascade up the visual tree searching the resource of parents).
However, assuming you can fix that you still have a problem. The use of SetValue on the Setters colleciton itself is nothing like what you actually need to be doing.
You need to be doing this:-
style.Setters.Add(new Setter(DataGridColumnHeader.BackgroundProperty, new SolidColorBrush(Colors.Red));
Of course this only works if the style doesn't already contain an Setter for the property. Hence a more robust version is:-
var setter = style.Setters
.OfType<Setter>()
.Where(s => s.Property == DataGridColumnHeader.BackgroundProperty)
.FirstOrDefault();
if (setter != null)
setter.Value = new SolidColorBrush(Colors.Red);
else
style.Setters.Add(new Setter(DataGridColumnHeader.BackgroundProperty, new SolidColorBrush(Colors.Red));
I'm trying to populate a ComboBox programatically. I am creating ComboBoxItems and would like to set their text (the text that is visible for the end-user) and their value (the object that I will handle in the background after the user has selected it.
However the ComboBoxItem seems to only have one member for these two requirements: the Content variable. At the same time this would not fit my needs as I want to distinguish the text and value properties and want to do this without data binding. Is there some viable solution to achieve this?
My current code looks as follows:
ComboBox comboBox;
ComboBoxItem item = new ComboBoxItem();
item.Content = "First Item";
item.Value = 1; // Does not work, no such member as Value!
comboBox.Items.Add(item);
Guess you can use the Tag property.