How do I shoop this particular WPF whoop? (changing visibility)



  • Hello people of superior intelligence (though not Hanzo story writing ability) to mine,

    I am having a problem with a WPF project I am working on and I am wondering if anyone can help.

    I have a ListView, that ListView is bound to a collection of complex objects, I have a Data Template which is:
    Border
    -Stack Panel
    --Textbox
    --Textbox
    --Listview A
    --Button

    ListView A is databound to another collection of complex objects that exists in each of the main objects. this list view has another data template which is currently simply:
    Border
    -StackPanel
    --Label
    --Label

    ListView A currently starts it's life as collapsed, and my plan was to make the Button change that visibility, Since the button is repeated I can't (to my understanding) use the codebehind to achieve this, as I wont know in the codebehind which button is which in the list. when I try and use an animation on an EventTrigger (RoutedEvent if that matters) in the StackPanel resources of the main data template, I get an exception when the button is pressed. Specifically:

    exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll

    Additional information: Cannot resolve all property references in the property path 'Visiblity'. Verify that applicable objects support the properties.

    No helpful information is provided in inner exceptions or anything. I have named the button and the listview that originate the event and are mutated by it respectively, and the origination clearly works, however the mutation is failing.

    Can anyone give me a solution? I am guessing the simplest solution would be to refactor this to a UserControl so I can use the codebehind, but is that the only solution?



  • As with everything WPF, this can be solved by Binding.



  • Ok, thanks for the above that gave me a pointer on how to progress further.

    For posterity: I have refactored my view, changing that button into a checkbox, and then binding that checkbox to a value in the model (a newly created boolean value against each item in the list), and then bound THAT value back to the visibility of the listview with the visibility converter.

    Everything works flawlessly!

    Thanks for the help



  • Follow-up question:

    The view I am putting this data into is long-lived - it's intended to be the main view that just sits there being always on unless the user is doing some other specific task.

    This means I have to occasionally poll the database for updated data, since EF doesn't by default reflect changes in the entities from external sources, I have to request fresh copies and propagate that into the view.

    I am currently doing this in the associated models for the view (not the viewmodel). I am setting up a background worker thread in the model class which will at a set interval pull fresh data out of the ef model.

    am I doing it wrong?


  • FoxDev

    @algorythmics said:

    am I doing it wrong?

    yes. you forgot to include a dependency on discourse for your long polling needs.

    :-P



  • I'm sorry I didn't see your follow up question, I just came back here to post something about commands, which I literally just discovered yesterday. I don't really know enough about best practices to comment, except to say that what you're doing does sound about right from what I can gather.

    Anyway, a different solution to your original problem (binding was probably the correct solution, but there are other problems where this might be relevant) might have been to use Microsoft's Commands SDK, which I think is included in VS2013. You'd need to add reference to the Commands SDK to your project, then add namespaces:

    xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
    xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
    

    then you would be able to bind actions to events like:

    <Interactivity:Interaction.Behaviors>
         <Core:EventTriggerBehavior EventName="Click">
             <Core:CallMethodAction MethodName="LoadListA" TargetObject="{Binding}"/>
        </Core:EventTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
    

    where the object the control is bound to has a method like void LoadListA(). There are more behaviors and actions available in the sdk, the easiest way to browse them might be from the Blend ‘assets’ tab.


Log in to reply