This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Hello Ivan! It's again me. I know that it's not your control error, but I have question. That is my code. void addArrayPropertyEditor(Int32 index) void updateArrayPropertyEditorUI() void buttonNext_Click(object sender, RoutedEventArgs e) When I load my controls the updateArrayPropertyEditorUI() function calls for the first time. then in my window I click on mButtonPrev. updateArrayPropertyEditorUI() function calls again. It gives me error: After a 'FrameworkElementFactory' is in use (sealed), it cannot be modified. in the place: if I'll comment this row it will raise the same error in the next place, where I use Frameworkelementfactory class control. Why does it happens? I'm doing something wrong? Please, help me solve it, thank you. |
|
|
What is happening is that, after the first run through this code, the DataTemplate gets instantiated. This seals the FrameworkElementFactory objects that make up the DataTemplate VisualTree. Now when your click handler calls updateArrayPropertyEditorUI(), it tries to modify mButtonPrev, mButtonNext, etc., which it's no longer allowed to do. Conceptually, the problem is that you're trying to modify the IsEnabled status of a button by modifying the template from which the button was created. That's not appropriate because even if WPF did allow you to do this, (a) the button is long since created, and (b) there might be many instances of this template and therefore many buttons. It's as if you'd loaded the template from XAML, then modified the XAML source: of course the changes wouldn't propagate to the button. What I suspect you really want to do is either (a) modify the IsEnabled property of the button *instance* or (b) choose a different template depending on the arrayProperty.getNum() result. For the former, this can be a little bit tricky because it's hard to get at the innards of an instantiated DataTemplate. You basically want to give your button a name, and then access it using FindName or GetTemplateChild. (The docs say to use FindName but I've had trouble getting FindName to see inside data templates.) Alternatively, instead of using SetValue to set the IsEnabled property, use SetBinding. This is equivalent to the XAML <Button IsEnabled="{Binding somePath}" /> which is the natural WPF way if you can find a suitable thing to bind to. For the latter, consider a DataTemplateSelector. The usual trick with these is to create a ContentControl FrameworkElementFactory and set its ContentProperty to the thing you want to display and its ContentTemplateSelectorProperty to your DataTemplateSelector. By the way, I didn't notice anything in your code that required the use of a FrameworkElementFactory. You probably only need a FEF if you don't know the template at design time. You may want to consider writing your template in XAML instead and loading it from your application or window resources. |
|
|
First problem is: I don't use XAML. All objects I create at runtime. I want to set IsEnabled property of the button *instance* depending on the arrayProperty.getNum() I tried to use SetBinding instead of using SetValue but it gives me the same error. I understand, that error occurs, because FrameworkElementFactory controls are sealed. Are any ways to solve it (can I change IsEnabled property for FrameworkElementFactory control at runtime?)
|
|
|
Fundamentally, no, you can't change the IsEnabled property (or any other property) for a FrameworkElementFactory at runtime (or, at least, not after the DataTemplate has been instantiated). What you can do is have multiple FrameworkElementFactories (DataTemplates), with the IsEnabled property set differently, or change the IsEnabled property of the element instance generated from the factory. The former approach may be appropriate if any given instance is always enabled or always disabled. The latter approach is required if a given instance may change between being enabled and disabled over time. I am not sure exactly what your scenario is but I think it is the latter. Assuming this is correct, there are two possible approaches here. In both cases, however, you do *not* call updateArrayPropertyEditorUI in the button click handler. As you've identified, the FrameworkElementFactory is sealed by this point and there would be no point changing it even if WPF allowed us to. Instead, your button click handler does one of two things: 1. Locate the generated button instance in code, and set its IsEnabled property. In this case, you can continue to use SetValue on your FrameworkElementFactory to set the initial value of IsEnabled. 2. Sets a property in an underlying data object, to which the button's IsEnabled property is bound. In this case, you would use SetBinding on the FrameworkElementFactory to bind the IsEnabledProperty to the relevant property. My instinct would be to prefer option 2. Create some sort of object that tracks the changing getNum() (or change getNum() itself to be a property that raises PropertyChanged events), and databind the buttonPrev and buttonNext IsEnabled properties to that. Then in your click handler, set the property, and let the IsEnabled property take care of itself. But you'll need to figure out whether this is an appropriate solution for your application and if so what would be an appropriate implementation. By the way, don't forget you can load XAML-based templates at runtime -- either using XamlReader.Load or FindResource(templateName). |
|