WP7 Pivot Title Template DataContext Binding not working - templates

I have a Pivot Title Template so that the Pivot page has a title and subtitle. I want to set both via code.
I build the XAML in Blend and without code binding, it does display so that part works.
However, my binding isn't working. It either won't build because the object doesn't have a DataContext, or the object doens't exist in current context or does build but won't display. When it doesn't display, I assume I'm binding to the wrong XAML object.Each object is named only so I could find the right object to bind to.
The containing class for the bound code of Title and Subtitle looks like:
public class PivotTitle
{
public string Title = "";
public string Subtitle = "";
}
My question is: how do I correctly bind the TitleTemplate so that the two TextBlocks' Text properties can be set in code?
Here is the XAML
<controls:Pivot.TitleTemplate >
<DataTemplate x:Name="PivotTitleTemplateDataTemplate" >
<StackPanel x:Name="MyPivotTitle" DataContext="{Binding}" >
<TextBlock x:Name="Title"
Text="{Binding Title}"
FontSize="20"
TextWrapping="Wrap"/>
<TextBlock x:Name="Subtitle"
Text="{Binding Subtitle}"
Foreground="Gray"
TextWrapping="Wrap"/>
</StackPanel>
</DataTemplate>
</controls:Pivot.TitleTemplate>
The title and subtitle are dependent on the page navigated from. The code behind looks like:
//defined at top of page class
public PivotTitle _PivotTitle = new PivotTitle();
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string queryStringDeploymentName = "";
this.NavigationContext.QueryString.ContainsKey("DeploymentName"))
_PivotTitle.Title = SelectedDeployment.DeploymentName;
_PivotTitle.Subtitle = App.ViewModel.AppSettings.UpdatedText;
MyPivotTitle.DataContext = _PivotTitle;
}
This particular example won't build with this error: The name 'MyPivotTitle' does not exist in the current context. The binding on the Pivot page's Listbox is working correctly.
I believe my codebehind and overall XAML are correct. I think I'm DataContext binding incorrectly.
Thanks for any help.

In your example MyPivotTitle is an element within the DataTemplate, so cannot be accessed directly from your code, hence the error. If you need to access a control inside a template of an items control (such as Pivot or ListBox`) then you may find this article from WIndowsPhoneGeek.com useful.
However, it sounds like you might be able to do this without any "hacking". Is this title and subtitle just for a single pivot item, or will it be on all of them? What other data, if any are you binding on the pivot item(s)?

Related

How to make a NameValueCollection list editable in GlassMapper

I am trying to make a NameValueList collection editable with GlassMapper and I don't seem to be able to get to the bottom of this.
We have a list of validations that can be attached to a field and I would like to have the validation message editable in ExperienceEditor.
The collection is pre-processed when GlassMapper is retrieving the item:
Validations = glassItem.GetValidations();
#foreach(Validation validation in Model.Validations)
{
<div id="#validation.Identifier" ng-message="#validation.AngularKey" ng-cloak class="mtg-validation-msg">
#Html.Glass().Editable(validation, e => e.ErrorMessage)
</div>
}
Error that I am getting:
Failed item resolve - You cannot save a class that does not contain a property that represents the item ID. Ensure that at least one property has been marked to contain the Sitecore ID. Type: MyAssembly.Models.Validation
It is not possible to directly edit certain types of complex fields in the Experience Editor, such as Treelist, Multilist or Name Value Collection.
Instead, you should set up and use an Edit Frame. This will pop up a modal dialog allowing you to edit the field, it is not inline but means you do not need to leave the Experience Editor. This is the recommended approach to this problem.
Since you are using Glass Mapper, since version 4 you can declare Edit Frames all directly from code and now have to declare/set them up in the Core database first.
#if (Sitecore.Context.PageMode.IsExperienceEditor)
{
using (Html.Glass().BeginEditFrame(Model, "Edit", x => x.Validations))
{
<div>Edit Validations</div>
}
}
You might be interested in this blog post I wrote about adding a wrapper around the Edit Frame to make the UX more friendly.

How to correctly bind TextBox Text property for attached behavior?

In studying the classic article by Josh Smith, Regex Validation in WPF,
I am having an error (VS 2010) of:
Error 134 The TextBox's Text property must be bound for the RegexValidator to validate it.
This is thrown at
<TextBox
Text="{Binding Path=DateString, UpdateSourceTrigger=PropertyChanged}"
jas:RegexValidator.RegexText="{x:Static local:DateFormatRegex.DateRegex}"
jas:RegexValidator.ErrorMessage="Invalid date format."
/>
It appears to me that the text is bound. What's wrong? (I have no clue :( ).
Any help is most appreciated.
TIA
You are seeing the error because you have not set a design-time DataContext for the XAML designer to work with.
You could do this in the XAML. Add this to the UserControl/Window attributes:
xmlns:local="clr-namespace:MyProjectName.ViewModels"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DataContext="{d:DesignInstance Type=local:MainViewModel, IsDesignTimeCreatable=True}"
(Replace your project name, ViewModel name, etc.)
If your ViewModel does not have a parameterless constructor, you can create an instance from the code-behind of the view, e.g.:
public MyControl()
{
DataContext = new MyViewModel("a parameter");
}
Obviously this has its limitations as the application is not executing.

CustomItemGenerator and the Page Editor

Sitecore 6.6 Update 4
We're using CustomItemGenerator 1.0 and I was using this to help build a primary navigation menu for a site. This worked as expected and everything was rendered properly.
My problem is when I attempt to edit the menu via Page Editor; I don't even see the menu.
I use a repeater and repeat over a list of links to include in the nav. Due to the way the HTML was created, each LI element needs to have its own, specific ID ("Nav Id" Field in Sitecore) that ties into the CSS. Code inside of my repeater's ItemDataBound event:
// Cast the item using CustomItemGenerator-generated class
GenericContentPageItem navItem = (GenericContentPageItem)e.Item.DataItem;
liMenuItem.ID = navItem.NavId.Rendered; // I tried "navItem.NavId" by itself as well
So while this renders properly in the browser, it doesn't when I'm in Page Editor:
<li id="<input id='fld_B72EB6696DCF41A49671972D5EA5DEB8_2163B90C08AB4A18970A7F3ECE79DCFC_en_1_f71bd37d18d146c19e222e89fcffe278_3' class='scFieldValue' name='fld_B72EB6696DCF41A49671972D5EA5DEB8_2163B90C08AB4A18970A7F3ECE79DCFC_en_1_f71bd37d18d146c19e222e89fcffe278_3' type='hidden' value=" Home?="">
... instead of it rendering like this:
<li id="Home">...</li>
Now, that having been said, I can change my code to not use the CustomItemGenerator and it works fine in the browser and Page Editor as follows:
GenericContentPageItem navItem = (GenericContentPageItem)e.Item.DataItem;
Item nav = Sitecore.Context.Database.GetItem(navItem.ID);
liMenuItem.ID = nav.Fields["Nav Id"].ToString();
I would like to avoid having to hardcode field names in my code, which is why I am using CustomItemGenerator. Is there something that I'm doing wrong with my code that it doesn't want to work in Page Editor?
Thanks!
If you need the actual value out of the field regardless of if you are in the page editor or not, you want to use the Raw property:
liMenuItem.ID = navItem.NavId.Raw;

Accessing Sitecore Properties for an Image field in user control's Code-behind

I want to access (and then modify) the properties for the image field(s) in Sitecore (esp. interested in 'Dimensions' and 'Keep Ratio' check box) via a code-behind file (blah.ascx.cs).
[This to ensure that all the images have a consistent size, when displayed in the sublayouts (irrespective of the original size)]
I know these properties can be added manually, but for the case where content authors "forget" to add the dimensions for image(s), I don't want my sublayouts to screw up. Hence, I need a check for that.
Is there a way to access and then modify these properties via code?
Here is an image that shows exactly what I want to access and modify via code:
If you're using an <asp:Image ... /> and binding the ImageUrl via C#, you can access the ImageField in C# and get the properties, like so:
Sitecore.Data.Fields.ImageField field = item.Fields["My Image Field"];
// you can now access:
// field.Width
// field.Height etc...
If you're using a <sc:Image ... /> renderer or a regular <sc:FieldRenderer ... /> I would recommend you use <sc:FieldRenderer ... /> as the image parameters only work on that, as documented here.
Here's a sample snippet:
<sc:FieldRenderer FieldName="My Image Field" Parameters="w=100&h=200&as=1" runat="server" />
This to ensure that all the images have a consistent size, when displayed in the sublayouts (irrespective of the original size
I'd suggest to use FieldRenderer class, or <sc:image> for rendering such fields in sublayouts, and then specify "mh" (max height) and "mw" (max width) parameters, so they will always fit into layout.
You can read more about parameters here - http://sdn.sitecore.net/Articles/XSL/5%203%20Enhancements/Image%20Enhancements.aspx
Not a 100% sure (can't check here), but if you retrieve the field as an ImageField you should be able to access those values.
var cur = Sitecore.Context.Item;
Sitecore.Data.Fields.ImageField imgfield = cur.Fields["imagefieldname"] as Sitecore.Data.Fields.ImageField;
//imgfield.<properties>

Orchard CMS: Creating bookmark for List item

We're creating a page in Orchard CMS using the 'List' Content Type. We want to add some hyperlinks at the top of the list, that will jump down the page to specific items in the list.
We specifically don't want to just link to the individual page for the list item, but jump down to where it is in the list, and because the list items are rendered using the same View part, we can't of course just hard code the bookmarks.
We've been customising the View Part in VS and know that the list item title is generated using the code:
#Display(Model.Header)
And this generates < h1 > and < a > tags to wrap around the title like this:
< h1 shape-id="5" >< a href="/Orchard/Contents/Item/Display/36" shape-id="5" >Marketing< /a >< /h1 >
However, we can't find a way to get the Display() method to include a 'name=' clause which we can then use as the bookmark.
We've also tried adding a new tag just above the exiting code, e.g.:
< a name="#Model.Header" >< /a >
#Display(Model.Header)
But of course the Model.Header is an object reference, and not some text, so this failed. After this we've got lost with various ways trying to find a property of the Model object to fetch the Title as text but couldn't.
There must be a way to overload the Display() method to get it to include the 'name=' clause, anyone got any ideas?
Model.Header is just a zone. What really renders the title is a shape that was added to that zone. You should really use Shape Tracing (part of the Designer Tools module) to understand what the hierarchy of shapes looks like. You don't need to "overload the display method". What you need is to override the template for the shape that is rendering the title (which is not Model.Header but something inside it).
You might want to read this: http://weblogs.asp.net/bleroy/archive/2011/03/27/taking-over-list-rendering-in-orchard.aspx and this http://weblogs.asp.net/bleroy/archive/2011/05/23/orchard-list-customization-first-item-template.aspx
Try:
<a name="#Model.Header.Items[0].Title" />
It's not pretty, but it worked for me when I dropped this in an alternate template for a biography content type I created (Views/Content-Bio.Summary.cshtml).
Based on Bertrand's suggestion, instead you can try:
<a name="#Model.Title" />
in your template alternate.