Can Styleselector be re-applied after changes to connector view model?

6 posts, 1 answers
  1. Michael
    Michael avatar
    26 posts
    Member since:
    Oct 2014

    Posted 13 Nov 2014 Link to this post

    Hello,

    I have a diagram in which shapes and connectors bound to implementations of NodeViewModelBase and LinkViewModelBase<> (respectively).  I also have a StyleSelector which sets the visual style of the connectors based on values in the underlying connector viewmodel.  So far so good.  Now I need to update connectors periodically, and the updates will necessitate changes to the visual styles of the connectors.  But, if a connector viewmodel is changed, the corresponding connection in the diagram does not have its style changed using the StyleSelector.  I did try raising the property changed event of the ObservableGraphSourceBase<> bound to the GraphSource property of the diagram, but this to did not force the StyleSelector to be re-applied.

    Is this intended behavior?  If so I can change style determination using converters or something else to handle the data changes.  If not, and using StyleSelectors to handle dynamic data changes that affect visual properties is the way to go, how do I get the Connector StyleSelector to be re-applied following changes to any of the diagram view models?

    Much Thanks,

    Mike

  2. Pavel R. Pavlov
    Admin
    Pavel R. Pavlov avatar
    1182 posts

    Posted 18 Nov 2014 Link to this post

    Hello Mike,

    In WPF StyleSelectors are applied during the initialization of the control, only. This means that when a StyleSelector finishes selecting all styles it will not be invoked again. 

    However, you do not need to reapply all the style over and over again. You can use binding to the properties that you need to change at runtime and update them through your ViewModel. The binding is designed to do that in WPF. 

    Do you mind sharing with us your exact requirements? Can you tell us which properties you need to change in which style and what user action will trigger that change?

    Regards,
    Pavel R. Pavlov
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. DevCraft banner
  4. Michael
    Michael avatar
    26 posts
    Member since:
    Oct 2014

    Posted 18 Nov 2014 in reply to Pavel R. Pavlov Link to this post

    Pavel,

    The question had to do with updating the look of a connector based on property changes of the bound connector view model.  The connector view model has an enum property upon which the initial selection of the style is made.  But, when this property is updated on any of the connector view models, the visual style of the connector in the diagram is not updated since the style selector is not re-applied.

    If I need to dynamically change connector visual appearance after the initial style has been applied, what is the preferred approach?  Should I change the approach and go with binding converters to the style definitions?

    Thanks,
    Mike

    Below is a short example of how I am defining styles and the selector and a connector view model with a enum property that drives the color of the connector.

    Styles:

    <Style x:Key="baseEdgeStyle"
           TargetType="telerik:RadDiagramConnection">
      <Setter Property="ConnectionType"
              Value="Polyline" />
      <Setter Property="TargetCapType"
              Value="{Binding TargetCapType}" />
      <Setter Property="SourceCapType"
              Value="{Binding SourceCapType}" />
      <Setter Property="StrokeThickness"
              Value="3" />
    </Style>
     
    <Style x:Key="edgeStyleSweet"
           TargetType="telerik:RadDiagramConnection"
           BasedOn="{StaticResource baseEdgeStyle}">
      <Setter Property="Stroke" Value="Yellow" />
    </Style>
    <Style x:Key="edgeStyleSour"
           TargetType="telerik:RadDiagramConnection"
           BasedOn="{StaticResource baseEdgeStyle}">
      <Setter Property="Stroke" Value="DarkOrange" />
    </Style>
    <Style x:Key="edgeStyleGrumpy"
           TargetType="telerik:RadDiagramConnection"
           BasedOn="{StaticResource baseEdgeStyle}">
      <Setter Property="Stroke" Value="Red" />
    </Style>
     
    <helpers:EdgeStyleSelector x:Key="edgeStyleSelector"
                               EdgeStyleSweet="{StaticResource edgeStyleSweet}"
                               EdgeStyleSour="{StaticResource edgeStyleSour}"
                               EdgeStyleGrumpy="{StaticResource edgeStyleGrumpy}" />

    Edge view model:

    public enum EdgeFlavor { Sweet, Sour,  Grumpy };
     
    public class EdgeViewModel : LinkViewModelBase<NodeViewModelBase>
    {
      private EdgeFlavor mFlavor;
     
      public EdgeViewModel() : base() { }
      public EdgeViewModel(NodeViewModelBase source, NodeViewModelBase target) : base(source, target)
      { }
     
      public EdgeFlavor Flavor
      {
        get { return mFlavor; }
        set
        {
          if (mFlavor != value)
          {  mFlavor = value; OnPropertyChanged("Flavor"); }
        }
      }
    }

    Selector:
    public class EdgeStyleSelector : StyleSelector
    {
      public override Style SelectStyle(object item, DependencyObject container)
      {
        EdgeViewModel edge = item as EdgeViewModel;
        if (edge != null)
        {
          switch (edge.Flavor)
          {
            case EdgeFlavor.Sweet:
              return EdgeStyleSweet;
            case EdgeFlavor.Sour:
              return EdgeStyleSour;
            default:
              return EdgeStyleGrumpy;
          }
        }
        return EdgeStyleGrumpy;
      }
      public Style EdgeStyleSweet  {get; set; }
      public Style EdgeStyleSour  {get; set; }
      public Style EdgeStyleGrumpy  {get; set; }
    }

  5. Answer
    Pavel R. Pavlov
    Admin
    Pavel R. Pavlov avatar
    1182 posts

    Posted 20 Nov 2014 Link to this post

    Hi Mike,

    The short answer is "absolutely yes". 

    I can see in your code that you actually need to change only the Stroke property of the RadDiagramConnection object. There is no need to re-apply the Style of the UI element just for one property. Please keep in mind that re-applying Styles and ControlTemplates are heavy operations and the performance can be affected. This is why in your particular scenario using bindings is the appropriate approach. Even if you use converter in the bindings the performance will not be affected as much as if you force the UI component to re-apply its style.

    Regards,
    Pavel R. Pavlov
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  6. Barış
    Barış avatar
    19 posts
    Member since:
    Jul 2015

    Posted 16 Oct 2015 in reply to Pavel R. Pavlov Link to this post

    hello,

    I use Pavel's solution in my project but, when I create link (both by adding to graphsource in code or drawing in diagram), Color converters work. But after I save the diagram xml to db, and load id back. It does not call Convert or Convert back functions.

     

  7. Martin
    Admin
    Martin avatar
    1099 posts

    Posted 21 Oct 2015 Link to this post

    Hello Barış,

    I am afraid without your implementation I cannot be absolutely sure what is causing the described behavior. However, I guess you are using the Save() and Load() methods of RadDiagram to serialize/deserialize it. If this is your case, keep in mind that by default the digarma control saves automatically several properties of its shapes. Additional properties should be saved manually in the serialization events of the diagram. When the diagram is deserialization the default saved properties are set locally by the serialization logic. Since a locally set property has bigger priority then a bound one, the bindings doesn't work anymore. In order to prevent this you can subscribe for the ShapeSerializaed and ShapeDeserialized events (or override the SerializeNode/DeserializeNode() methods in MVVM scenario) and save the default serialized properties which are bound with a key different then the default one. You can take a look at the Preserve bindings to the automatically serialized properties section from the Serialization help article.

    Regards,
    Martin
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
DevCraft banner