Visual Basic form property array don't get stored - arrays

here's my issue:
I made an UserControl containing a ListView called "lstMain".
I have a property inside my controller:
Public ReadOnly Property DataRowBoundColumns() As System.Windows.Forms.ListView.ColumnHeaderCollection
Get
Return Me.lstMain.Columns
End Get
End Property
In the designer I can edit such property BUT when I compile the value gets deleted.
This doesn't happen for the other properties, which are a String, an Integer and other objects (not arrays).
Can anyone help me?

The problem is that the data you provide through the collection editor in design mode, do not get serialized.Assuming that your custom control is called "MyCompositeControl" you should write something like the following.
Imports System.ComponentModel
Public Class MyCompositeControl
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
Public ReadOnly Property DataRowBoundColumns() As System.Windows.Forms.ListView.ColumnHeaderCollection
Get
Return Me.lstMain.Columns
End Get
End Property
End Class

Related

Hide a property from an observablecollection

So I have a WPF DataGrid bound to an ObservableCollection, which contains a single instance of a class - for example:
Public Class parent
Public Property title As String [...]
Public Property someCommonThing as Integer [...]
Public Class Child Inherits Parent
Public Property name As String [...]
Public Property address As String [...]
Public Class Window1
Dim oc As ObservableCollection(Of Object) = New ObservableCollection(Of Object)
oc.Add(New Child())
dataGrid.ItemsSource = oc
there are many child classes with different properties, hence why I can't easily define the datagrid columns directly.
I want to be able to hide certain parent properties from the datagrid (for example, never show the title property in the datagrid), while still being able to use it for databinding elsewhere (e.g. a label).
Is this possible? I can't think how to do it without manually specifying every column for every possible class instead of using the databinding.
When automatically generating columns you can change the per-property behavior using Data Annotations, in this case specifically the BrowsableAttribute class:
<Browsable(False)>
Annotating your property with this will prevent a column from being generated when using the following event handler on the AutoGeneratingColumn event of the DataGrid.
Private Sub OnAutoGeneratingColumn(sender As Object, e As DataGridAutoGeneratingColumnEventArgs)
If Not DirectCast(e.PropertyDescriptor, PropertyDescriptor).IsBrowsable Then
e.Cancel = True
End If
End Sub
Remember to add the DataAnnotations assembly to your project.

WPF updating parameterized bindings

I have a property in a class:
Default Public ReadOnly Property GetLiteral(Key As String) As String
Get
Try
Dim Row() As String = _LookupTable.Item(Key)
Return Row(_CurrentLanguage)
Catch ex As Exception
Return ("Error")
End Try
End Get
End Property
And I bind a label to it:
<Label Content="{Binding SLP.[LITERAL_USERNAME]}"/>
Where SLP is a public property in my view model containing an instance of the class containing the default property GetLiteral.
The above binding works fine. I can select different languages in my view. However, I wish to also be able to change languages on the fly, and I can't figure out how to raise INotifyPropertyChanged in order to make this binding update. I know I could probably achieve this easily with a value converter and parameter, but I like the simplicity of the XAML above.
Thanks.
I figured it out. I was calling NotifyPropertyChanged from inside SLP, where what I really needed to do was call NotifyPropertyChanged(Me, "SLP") from the View Model.

Changing the path a property is bound to at runtime

I have a ComboBox with a list of objects bound to it.
Currently i have the items templated so they show only the property Class.Name. so the ComboBox is full of Class.Name
However i am required to give the user the option to display the property Class.Description instead. If it were just that easy i would be fine, but they want the option to switch back and forth between them at runtime.
Any ideas?
You can probably do this directly in WPF.
I would alter the business objects to include an additional Readonly property, something like, DisplayTextProperty
Public ReadOnly Property DisplayTextProperty()
Get
If ShowDescription Then
Return Description
Else
Return Name
End If
End Get
End Property
I have done this in a few places now and it works great.

DataContext, DataBinding and Element Binding in Silverlight

I'm having one hell of a time trying to get my databinding to work correctly. I have reason to believe that what I'm trying to accomplish can't be done, but we'll see what answers I get.
I've got a UserControl. This UserControl contains nothing more than a button. Now within the code behind, I've got a property name IsBookmarked. When IsBookmarked is set, code is run that animates the look of the button. The idea is that you click the button and it visually changes. We'll call this UserControl a Bookmark control.
Now I have another control, which we'll call the FormControl. My FormControl contains a child Bookmark control. I've tried to do databinding on my Bookmark control, but it's not working. Here's some code to help you out.
This is the XAML and Loaded event handler of my control. As you can see it contains a child element that is a custom control (bookmark). So once this control loads, it's DataContext is set to an new instance of an Employee object. Silverlight also sets the DataContext property of my child bookmark control to the same instance. I've verified this by debugging. If my parent has a valid DataContext set then why can't my child control (bookmark) property databind to it?
<UserControl ......>
<q:Bookmark x:Name="BookMarkControl1" IsBookmarked="{Binding IsSiteBookmarked}" />
</UserControl>
public void Control_Loaded(object sender, EventArgs e)
{
DataContext = new Employee { IsSiteBookmarked = True };
}
This is my custom control below. Obviously it contains more than this, but for readability I've trimmed it down to the property I'm trying to databind to.
//this is the bookmark control. I've included this control within another control, and I'm trying to databind to properties within my parents DataContext
public partial class Bookmark : UserControl
{
bool _IsBookmarked= false;
public bool IsBookmarked
{
get {return _IsBookmarked;}
set {
_IsBookmarked= value;
SwitchMode(value);
}
}
}
UPDATE
Got some javascript errors that I should mention. Firebug reports a AG_E_PARSER_BAD_PROPERTY_VALUE exception. It doesn't seem like my databinding is even working yet.
Make your IsBookmarked property on the Bookmark control a dependency property.
I presume Control_Loaded is a part of your FormControl, in which case I'm not sure you are using DataContext properly. Best double check that.
UPDATE: Yes, you are using the DataContext properly. AG_E_PARSER_BAD_PROPERTY_VALUE indicates you need to make the IsBookmarked property a dependency property, like so:
Public Property IsBookmarked() As Boolean
Get
Return Me.GetValue(IsBookmarkedProperty)
End Get
Set(ByVal value As Boolean)
Me.SetValue(IsBookmarkedProperty, value)
End Set
End Property
Public Shared ReadOnly IsBookmarkedProperty As DependencyProperty = DependencyProperty.Register("IsBookmarked", GetType(Boolean), GetType(Bookmark), New PropertyMetadata(New PropertyChangedCallback(AddressOf OnIsBookmarkedPropertyChanged)))
Private Shared Sub OnIsBookmarkedPropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
Dim cntrl As Bookmark = TryCast(d, Bookmark)
cntrl.SetIsBookmarked(e.NewValue)
End Sub
If you only need to store the value for later use, then you don't need to do anything in the OnIsBookmarkedPropertyChanged procedure, But I put some code there as an example anyway.
Good Luck!
I don't recall the exact order in which databinding is evaluated (and I'm too lazy to go look it up), but as I recall, it initially happens BEFORE the form's Loaded event fires, and without making the IsBookmarked property a dependency property, or at least using INotifyPropertyChanged, it may have trouble establishing the datacontext appropriately. I'd recommend either implementing INotifyPropertyChanged or making IsBookmarked a dependency property. DataBinding is tough enough to get right in the best of circumstances (see my long, bad-tempered rant about it here), and you'll just be making it more difficult on yourself if you aren't setting up your properties in the way that it expects.
The control exposes a IsSiteBookmarked property(which I believe should be a DependencyProperty) but the control is binding to a IsBookmarked which is not shown. Is this intentional? Have you checked your Visual Studio output window for binding errors?
Addition 1:
Since you have fixed the typo in your question and added that there is an error being reported.
Start by clearing up the AG_E_PARSER_BAD_PROPERTY_VALUE problem. Is there a line number and start position in the error message? Start looking there. One strategy is to start taking out XAML until there is no longer an error. This will narrow down the offending code.
Running in debug, mode check for binding errors in the output window.
You might want to also post the Employee class code, especially the IsSiteBookmarked property.
Typically when doing databinding to an object you will want to leverage the INotifyPropertyChanged interface and implement that so that the control can properly invalidate it's property value. Unless you use INotifyPropertyChanged with Mode=TwoWay then any code that changes your DataContext's IsSiteBookmarked will have no effect.

Basic WPF question: How to add a custom property trigger?

I am using Expresion Blend 3 and created a new user control in my project. I want a storyboard to run if a custom property of that user control is triggered like with the ones shown here in the list..
I learnt you need a dependency property, but my understanding there is limited. Here's the basic code I set up with property "IsAwesome" as an example..
Partial Public Class simpleControl
Public Sub New()
MyBase.New()
Me.InitializeComponent()
End Sub
Public Shared ReadOnly IsAwesomeProperty As DependencyProperty = _
DependencyProperty.Register("IsAwesome", GetType(Boolean), GetType(simpleControl))
Public Property IsAwesome() As Boolean
Get
Return DirectCast(Me.GetValue(IsAwesomeProperty), Boolean)
End Get
Set(ByVal value As Boolean)
Me.SetValue(IsAwesomeProperty, value)
End Set
End Property
End Class
However, my property doesn't show in that list. What am I missing? Or is my entire approach wrong?
Any help or advice would be appreciated!
Cheers
I created a new Wpf project. Added a new UserControl (UserControl1) with a custom dependency property called Foo.
Then I opened Blend and added an instance of UserControl1 to Window1. I right clicked on UserControl1 and said EditTemplate | Edit a Copy.
This created a copy of my user control template in the Window.Resources. From within this new template I went up to the Triggers panel and clicked the button to add a new property trigger.
Right away Blend defaulted to selecting my property in the "Activated When" section.
alt text http://blog.BradCunningham.net/Images/ForumImages/CustomDPInBlend.png
You can grab my little sample app from here: http://blog.BradCunningham.net/SourceCode/ForumSamples/CustomDPInBlend.zip

Resources