Is there way to ignore Ids generated to Binding class - android-viewbinding

When using viewBinding with ConstraintLayout, maybe a lot of Ids will be create to help describe the view relationship, but will never used in Kotlin/Java.
I just found two useful tools attribute
tools:viewBindingIgnore="true" used to prevent whole layout generated in Binding, but not for single Id.
tools:viewBindingType="TextView" used for changing the Type generated in Binding.
So is there any way to ignore Id(s)? I don't want to expose them to pollute the Kotlin/Java.

Currently, there is no way to ignore view binding generation on view by view basis. If you use Proguard the unused ViewBinding IDs will be removed from the final APK.

Related

How to bind from DataTemplate to Page's DataContext?

I've got a page where a DataTemplate is being used to bind to the model for that content, e.g.:
<DataTemplate x:DataType="models:MyDataType">
... content ...
</DataTemplate>
In that content, I need to be able to bind a Click event. I need that click event to exist in the view model that is set as the page's DataContext:
<Page.DataContext>
<vm:MyViewModel x:Name="ViewModel">
</Page.DataContext>
but I'm really struggling with getting it to compile. Every approach I try results in the compilation error "Object reference not set to an instance of an object".
I know I can't use x:Bind because that will bind to the DataTemplate's DataContext, so I've been trying to use Binding and, based on other SO answers I've read, it seems like the answer should be:
Click="{Binding DataContext.Button_Click, ElementName=Page}"
where Page is defined as the x:Name for the Page. I've tried removing DataContext. I've tried adding ViewModel.
What am I misunderstanding? Is it not possible to do what I want to do? I've tried using code-behind instead but I'm using Template 10 and that pushes almost everything onto the view model, which makes it harder for me to access things like the navigation service from code-behind.
tl;dr; use Messaging.
#justinXL is right, 'ElementName' can work. But is it best?
The problem you are trying to solve has already been solved with messaging. Most MVVM implementations include a messaging solution. Prism uses PubSubEvents; MVVM Light has its own messenger. There are others, too.
The idea is that an outside class, typically described as a message aggregator, is responsible for statelessly receiving and multicasting messages. This means you need to have a reference to the aggregator but not a reference to the sender. It’s beautiful.
For example
A common use case might be a mail client and how the data template of a message in the list would include a trash/delete button. When you click that button, what should be called? With messaging, you handle the button_press in the model and send/publish a message (one that passes the item).
The hosting view-model has subscribed to the aggregator and is listening for a specific message, the Delete message that we just sent. Upon receipt, it removes it from the list and begins the process to delete it from cache/database, or whatever – including prompting the user with “Are you sure?”
This means all your data binding in your data template is local, and does NOT extend outside its local scope. Why does this matter? Because if you use Element Binding to reach the hosting page, it means you cannot 1) move this template to a resource dictionary or 2) reuse this template.
There are two other reasons.
you cannot use compiled x:Bind to do this because it already limits use of this painful binding approach – this matters because a data template is typically in a list, and performance should always be prioritized, and
It adds considerable complexity.
Complexity?
I am a big fan of sophisticated solutions. I think they are rare and are the trademark of truly smart developers. I love looking at such code/solutions. Complex is not the same as sophisticated. When it comes to complexity, I am not a fan. Data binding is already difficult to wrap your head around; multi-sourcing your data binding across scope boundaries is pure complexity.
That’s what I think.
Your binding expression is correct, except it won't work with a Button_Click event handler. You will need an ICommand defined in your page's ViewModel.
Since you are using Template10, you should be able to create a DelegateCommand called ClickCommand like this
private DelegateCommand<MyDataType> _clickCommand;
public DelegateCommand<MyDataType> ClickCommand
{
get
{
_clickCommand = _clickCommand ?? new DelegateCommand<<MyDataType>>((model) =>
{
// put your logic here.
});
return _clickCommand;
}
}
And the binding will be updated to
<Button Command="{Binding DataContext.ClickCommand, ElementName=Page}" CommandParameter="{x:Bind}" />
Note I have also added a CommandParameter binding to the button as you might want to know which MyDataType instance is associated with the clicked button.

How to force one method on Razor ambiguous reference?

On one MVC 4 project, we have a lot of Pages.cshtml that receive a collection of Models (generally hundreds of rows), which we serialize as JSON via
#Html.Raw(Json.Encode(Model));
The problem is that on some of those pages we are receiving an exception (The length of the string exceeds the value set on the maxJsonLength).
We know what is the reason and how to fix it. The thing is that I would like to create a similar Json.Encode() method (using Json.Net), so we do not need to modify all the cshtml pages. If I create a Json.Encode() method, Razor complains about ambiguous reference between My.Namespace.Json and System.Web.Helpers.Json.
Again, we know how to solve this by adding an alias on the page:
#using Json = My.Alias.Json
What I'm trying to do is to transparently instruct Razor to choose this alias for all the cshtml pages that uses this Json.Encode. The reason is that I want this to be transparent, so later if somebody adds a new page, automatically he will start to use our custom JSON implementation.
I think on Views/Web.config you can add namespaces and some configurations for Razor, but I don't see how to explicitly set the aliases.
Interesting issue, but as far as I know that's not possible. See e.g. this: C#: Globally alias a generic class name?
As an alternative you could create a helper method Html.JsonEncode() and teach, drill or entice everyone to use that.
If you make it also do the Raw() call and return IHtmlString, then you can do #Html.JsonEncode(Model) as opposed to #Html.Raw(Html.JsonEncode(Model)) and before you know it everybody is a fan of your new method.

MVC: Set Name Attribute w/Helper

I have a situation in an MVC3 app where I would like to be able to set the name attribute on some html being generated by a helper (DropDownList).
It appears this is not possible. Apparently the helpers silently override whatever value you may specify for the name attribute in the html attribute object that you pass to the helper.
I'd like to confirm that before I waste too much more time on trying to work with the existing helpers.
And, as an aside, if it is not possible by design...I think that's a foolish limitation in the MVC framework. Yes, I know that assigning the wrong name attribute can break the automatic model binding. But I should be able to do that when I need to. After all, I can always write the raw html using whatever name attribute I chose. The helpers should help, not be a straitjacket.
Edit to discuss whether editor templates maintain navigational context
Darin, I am using editor templates (I was using the term "partial" generically, since editor templates are a special kind of partial view).
Editor templates do modify the HtmlFieldPrefix -- that's how I noticed I had a problem :). I was using a call like this:
// call in higher level partial - context is 'eae'
#Html.EditorFor(m => m.Value)
...
// inside editor template for typeof(Value) context is 'eae:Value'
That context shift is needed to keep the default binding mechanism working properly. I'm using a different approach, where I want the context to stay fixed throughout a call chain of partials (i.e., as execution burrows down into deeper partials I want the context to stay the same).
This is by design. The HTML helpers do not allow you to override the name attribute. They generate the name based on your view model so that the default model binder is able to properly bind the values according to the well established conventions when the form is submitted.
And, as an aside, if it is not possible by design...I think that's a
foolish limitation in the MVC framework.
You could open a ticket on MS Connect and hope this could change in a future version of the framework. Until then you could also write your own custom helpers that will allow you to override the name attribute for the cases when you need such functionality. Personally I've never needed it so far but I am sure you have valid reasons. Another possibility is to write a custom model binder on the server.

Why is System.ComponentModel.DataAnnotations.DisplayAttribute sealed?

I was going to implement a custom DisplayAttribute in order to allow dynamic display values based on model values, but I can't because DisplayAttribute is sealed.
Before I go off and write my own customer attribute that emulates the behavior of DisplayAttribute, can anybody think of why this is sealed? I'm assuming there is a reason behind it, and if so, that may be the same reason I shouldn't try to "hack" around this limitation by rolling my own.
I'm not asking anyone to read Microsoft's mind, I'm just hoping someone already knows the by-design reason it's sealed, so that I can take that into account when rolling (or avoiding) my own implementation.
In general it is considered best practice to seal attributes. FxCop has a rule about it, defined here. From that page:
The .NET Framework class library provides methods for retrieving custom attributes. By default, these methods search the attribute inheritance hierarchy; for example Attribute.GetCustomAttribute searches for the specified attribute type, or any attribute type that extends the specified attribute type. Sealing the attribute eliminates the search through the inheritance hierarchy, and can improve performance.
Many of the MVC attributes (ActionFilter, etc) are unsealed because they are specifically designed to be extended, but elements in the DataAnnotations namespace are not.
Not exactly what you asked, but following your intent...
You can still allow for dynamic display values, you just wont extend the DisplayAttribute.
Instead, you can implement your own IModelMetadataProvider which could contain any logic needed to create dynamic display values.
Brad Wilson, from the ASP.NET MVC team, has a good article and sample of this on his blog: http://bradwilson.typepad.com/blog/2010/01/why-you-dont-need-modelmetadataattributes.html

When is it right to use ViewData instead of ViewModels?

Assuming you wanted to develop your Controllers so that you use a ViewModel to contain data for the Views you render, should all data be contained within the ViewModel? What conditions would it be ok to bypass the ViewModel?
The reason I ask is I'm in a position where some of the code is using ViewData and some is using the ViewModel. I want to distribute a set of guidelines in the team on when it's right to use the ViewData, and when it's just taking shortcuts. I would like opinions from other developers who have dealt with this so that I know my guidelines aren't just me being biased.
Just to further Fabian's comment; you can explicitly ensure viewdata is never used by following the steps outlined in this article. There's really no excuse not to use models for everything.
If you have no choice but to use ViewData (say on an existing project); at the very least use string constants to resolve the names to avoid using 'magic strings'. Something along the lines of: ViewData[ViewDataKeys.MyKey] = myvalue; Infact, I use this for just about anything that needs to be "string-based" (Session Keys, Cache Keys, VaryByCustom output cache keys, etc).
One approach you may wish to consider as your views become more complex, is to reserve the use of Models for input fields, and use ViewData to support anything else the View needs to render.
There are at least a couple of arguments to support this:
You have a master-page that requires some data to be present (e.g. something like the StackOverflow user information in the header). Applying a site-wide ActionFilter makes it easy to populate this information in ViewData after every action. To put it in model would require that every other Model in the site then inherit from a base Model (this may not seem bad initially, but it can become complicated quickly).
When you are validating a posted form, if there are validation errors you are probably going to want to rebind the model (with the invalid fields) back to the view and display validation messages. This is fine, as data in input fields is posted back and will be bound to the model, but what about any other data your view requires to be re-populated? (e.g. drop-down list values, information messages, etc) These will not be posted back, and it can become messy re-populating these onto the model "around" the posted-back input values. It is often simpler to have a method which populates the ViewData with the..view data.
In my experience I have found this approach works well.
And, in MVC3, the dynamic ViewModels means no more string-indexing!
I personally never use ViewData, everything goes through the Model, except when im testing something and i quickly need to be able to see the value on the view. Strongtyping!
In terms of ASP.NET MVC 2, ViewModel pattern is the preferred approach. The approach takes full advantage of compile time static type checking. This in combination with compiling mvc views will make your development work-flow much faster and more productive since errors are detected during build/compile time as opposed to run time.

Resources