0

Is there a "Control" in WPF, which acts as a do-nothing, show-nothing storage repository for a single piece of bound data? Basically, an invisible control which exposes only a "Tag" DependencyProperty.

I'd like to use such a control as a way to consolidate some of my 'frequently used' data bindings into a single location. If I later change the name of the ViewModel property, I only have to update the binding in one place; my 'tag' control.

Ex:

<!-- Does this type of control exist? -->
<StorageControl x:Name="someData" Tag="{Binding MyProperty}" />
<StorageControl x:Name="moreData" Tag="{Binding MyOtherProperty}" />

<!-- further down the XAML file... -->
<TextBlock Text="{Binding Tag, ElementName=someData}">
    <Image.Style> 
        <!-- Style makes reference to "someData" and "moreData," -->
        <!-- with data triggers effecting the appearance. -->
    </Image.Style>
</TextBlock>
<Image>
    <Image.Style> 
        <!-- Style makes reference to "someData" and "moreData," -->
        <!-- with data triggers effecting the appearance. -->
    </Image.Style>
</Image>

Such a control would also allow me to 'flatten' an other-wise complicated and deeply-nested ViewModel structure, within a single View. I could also use it as a placeholder when stubbing out a user interface mockup, and I have not yet generated the ViewModel.

Another ideal usage scenario would be as an alternative to creating a single-use "IValueConverter" class. As an example: rather than trying to fliter a data-bound value through an IValueConverter, in order to get a resulting "Opacity," I could just 'style' the StorageControl to present the correct value using DataTriggers:

<StorageControl x:Name="opacityHost">
    <StorageControl.Style>
        <Style TargetType="StorageControl">
            <Setter Property="Tag" Value="1.0" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding MyProperty}">
                    <!-- This opacity trigger can now be used -->
                    <!-- by many other controls, without overriding their style -->
                    <Setter Property="Tag" Value="0.5" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </StorageControl.Style>
</StorageControl>

I realize I could craft my own, but this seems like a generic-enough control that it might already exist.

Would I just use FrameworkElement in this scenario?

BTownTKD
  • 7,911
  • 2
  • 31
  • 47
  • 2
    We see this on this website over and over again... *how can I reduce the amount of XAML that I have to write?* Please save yourself a whole load of trouble and just accept that XAML is a verbose language and it will always be like that. The more *unusual* code that you put into your code, the more confusing and error-prone it will become. – Sheridan Jun 02 '14 at 14:59
  • While I don't mind writing more code, I'd like to avoid writing more 'duplicate' code. I think the distinction there is important, and the latter is the thing I'm trying to avoid. – BTownTKD Jun 02 '14 at 15:01
  • 1
    Every WPF developer writes duplicate code... I hated it when I first started doing this, but after trying many different ways to simplify the situation, I have long since accepted that fact. If you insist on continuing, then the answer is no, there is no built-in control to do what you want. However, rather than extending the `FrameworkElement` class, with its hundreds of members that you won't use, you'd be better off extending a `DependencyObject` and adding your own `Tag` property. – Sheridan Jun 02 '14 at 15:06
  • @Sheridan I have to disagree with your statement that "XAML will always be verbose" - it doesn't have to be like that. I have posted several requests at uservoice for several features similar to what the OP is asking (not exactly like this but rather allowing FrameworkElement.Triggers to contain DataTriggers and things like that). There's things that would be easy for MS to do that would reduce verbosity a LOT (another example is project-wide xmlns and adding `[ContentProperty("Value")]` attribute to the Setter class) – Federico Berasategui Jun 02 '14 at 16:13
  • @BTownTKD BTW, ReSharper's rename feature also updates usages throughout XAML when you rename a property used in DataBinding, if that is your concern. – Federico Berasategui Jun 02 '14 at 16:20
  • 1
    XAML will always be verbose. Even if you remove the duplication it's still based on XML which is an inherently verbose language. Just the closing tags alone make it verbose! – Cameron MacFarland Jun 02 '14 at 17:35

1 Answers1

0

As far as I remember, such control does not exist, but you can easily write it. It literally would consist of a:

class MyDataHolder : Control
{
    // now add here one DependencyProperty that DONT have "AffectsXYZ" flags
    // or many DepProps if you want to 'gather' more things in one place
}

Actually, considering that you always can set Visible=Collapsed and Bindings still work, you might also use simple ContentPresenter/ContentControl, collapsed, and use their Content property has the "Tag". I used that trick a few times when I was in a real hurry.

However, mind that this is not a way to go. It will make some things easier, but evetually you will be going the naiive WinForms way taught on some courses that everyone strived to avoid due to many problems.

If you inspect carefully the 'Control+DP' way, you will learn few tricks how to make better "lookless controls". Also, if you think about it more, you will eventually strip the "DP" and "Control" part and you will "discover" the ViewModel, which will enable you to test your UI behaviours.

Lookless controls+Styles allow you to write Biindings once and reuse the style.

"Composite Styles" (search on the web! keywords: composite, merge, multi, etc) allow you to apply multiple styles to the same control, with some limitations of course.

Finally, if would like to add to all that the AttachedDependencyProperty, search about idea of "Behaviors", that will allow you to inject arbitrary code by XAML. This will allow you to write i.e. relatively simple scanners/observers that will walk though visual tree and apply any custom styles, bindings, etc automatically.

No free luch though - some of these end up in more complex code. Debugging clashes between 2 or 5 behaviours applied to the same control can be, well, haunting.

EDIT:

notes/links to "Composite Styles" I've managed to find:

Community
  • 1
  • 1
quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
  • 1
    Extending from `Control` is an even worse idea that extending `FrameworkElement` as it has even more properties, events and methods that would not be used. Why extend a class who's functionality you have no interest in using? – Sheridan Jun 02 '14 at 15:28
  • "Composite Style" sounds like an interesting concept that I have not run across, before. A google search for "WPF Composite Style" actually did not provide any results; could you elaborate on that concept, and perhaps provide a resource? – BTownTKD Jun 02 '14 at 15:46
  • @Sheridan: try reading further. It was an example of a not-so-good solution. I tried to navigate the reader to ViewModels and other better solutions – quetzalcoatl Jun 02 '14 at 17:00
  • @BTownTKD: Indeed, I almost can't find any! Seems like the topic died some time ago? I don't know. I've managed to find one implementation in my bookmarks, see here: http://stackoverflow.com/questions/5745001/xaml-combine-styles and http://www.zagstudio.com/blog/384#.U4yuunLV8Uo I'll drop more if I find any. I'm pretty sure I've seen at least three implementations of "composite style", all quite similar. This one here was the most interesting as it used markup extensions. – quetzalcoatl Jun 02 '14 at 17:05
  • @Quetzalcoatl, I can't read any further because you seem to have deleted your previous comment. – Sheridan Jun 03 '14 at 07:51
  • @sheridan: I was editing my last comment to include links and I hit the "5 minutes period" timeout. So, I deleted it and pasted once more with corrections. The comment starting with "Indeed" is a close copy of what has been deleted. I dont see it now however, so I can't check. Can you by chance? Nevertheless,in my "try reading further" response I was not referring to the comments,but to the text of my main answer. At its beginning indeed I was talking about subclassing Control/etc, but in later part of the text I tried to point the reader to better solutions. This is what I meant by "further". – quetzalcoatl Jun 03 '14 at 11:17