I have a componentart:GridColumn date column, currently it sets it FormatString like this
`
<componentart:GridColumn DataField="DtofExpiry" HeadingText="Date Of Expiry" EditCellServerTemplateId="PickerTemplate"
FormatString="MM/dd/yyyy" Width="100" AllowEditing="True" EditControlType="Custom"
/>
`
I want to set this FormatString from the code behind. I have tried putting it like this
FormatString='<%Appconfigures.ApplicationConfiguration.GetConfigurationByKey("AppDateFormat").ToString()%>'
but it gives me an error
Error:Databinding expressions are only supported on objects that have a DataBinding event. ComponentArt.Web.UI.GridColumn does not have a DataBinding event.
Related
I'm trying to implement a tab control, where each item comes from an ICollectionView of my viewmodel. Each tab page, for the items from the ICollectionView will be the same. However, I would like there to be an extra tab page for configuration options.
So an example tab header 'screenshot' might be:
tabA | tabB | tabC | config
on another instance, it could be
tabA | config
or
config
I can define the header for each item using ItemTemplateSelectors, and the content using the ContentTemplateSelectors. So that bit should be okay.
I'm having trouble with adding the config page item since I do not know where to add it. I thought I could set the tab's ItemsSource to be a CompositeCollection, where the final item is the config page object. I have failed to achieve this.
In the following example, I can view the tab headers being populated correctly according to the designer sample data which I have set up - I have not yet added the config page.
<controls:MetroTabControl ItemsSource="{Binding View}">
<controls:MetroTabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value.siteDisplayName}" />
</DataTemplate>
</controls:MetroTabControl.ItemTemplate>
<controls:MetroTabControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value.siteComment}"/>
</DataTemplate>
</controls:MetroTabControl.ContentTemplate>
</controls:MetroTabControl>
As you see, I have set the ItemsSource to be {Binding View}. This "View" comes from my ViewModel and is an ICollectionView.
Ideally i'd be able to do some magic like:
<controls:MetroTabControl>
<controls:MetroTabControl.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding View}"/>
<SomeConfigPageObject/>
</CompositeCollection>
</controls:MetroTabControl.ItemsSource>
...snip...
</controls:MetroTabControl>
But the problem is that when I do the above, the designer preview of the control acts as if there are no items in the ItemsSource.
For reference, each item in the {Binding View} is a object which contains a Value property, the value property containing an object that contains, in this example, a siteDisplayName and siteComment.
For reference, the DataContext for the tab is defined the dockpanel that contains it, as follows.
<DockPanel DataContext="{Binding Source={StaticResource Configurator}}"
d:DataContext="{d:DesignInstance cfuid:ConfigSiteVMSampleData, IsDesignTimeCreatable=true}"
LastChildFill="True">
For reference, the Configurator is my viewmodel and is instantiated in the xaml as:
<UserControl.Resources>
<ResourceDictionary>
...snip...
<cfvmc:ConfigSiteVM x:Key="Configurator" />
...snip...
So, the actual question would be:
How do I add my "config page" at the end of the tab control? Preferably via using the above-hoped method of adding an extra config-page object on the CompositeCollection; however if this is not possible [1] i'm open for suggestions.
[1] I think it doesn't work because the {Binding View} is an ICollectionView and the CompositeCollection requires a "collection" and doesn't accept a "view"
Thank you.
Peter.
I decided to do it through code behind. This means that I do lose my ability to use the design-time data to preview my UI; but it works at run time.
So, in the xaml I have.
<controls:MetroTabControl Grid.Column="0" Grid.ColumnSpan="2"
Grid.Row="0" Grid.RowSpan="2"
ItemsSource="{Binding ElementName=ucMe, Path=TabSitesCollection}">
Where ucMe is the UserControl and TabSitesCollection is a
protected CollectionViewSource m_TabSitesCollectionViewSource;
protected CompositeCollection m_TabSitesComposites;
public ICollectionView TabSitesCollection
{
get { return m_TabSitesCollectionViewSource.View; }
}
That gets initialised in the constructor as follows
public ConfigSiteView()
{
m_TabSitesComposites = new CompositeCollection();
m_TabSitesCollectionViewSource = new CollectionViewSource();
m_TabSitesCollectionViewSource.Source = m_TabSitesComposites;
InitializeComponent();
}
Then, on the Loaded event I can do
m_TabSitesComposites.Add(new CollectionContainer() { Collection = GetModel.View });
m_TabSitesComposites.Add(new TabItem() { Header = "hi" });
m_TabSitesComposites.Add(new TabItem() { Header = "ho" });
This results in almost my desired UI
I now simply need to spiff up my settings tab item and i'm done.
For reference, the xaml designer does not have any preview data - Unless I change the xaml so that the preview loads up (which then breaks the actual execution)
It would have been nice to have it both work while running, and on preview, but I haven't figured out how to do that, and it's not a current priority.
I'm using a content dialog do display instance data when an item in a grid is selected.
In the calling page's view model, when an item is selected the following method is executed.
public virtual void ItemSelected(object sender, object parameter)
{
var arg = parameter as Windows.UI.Xaml.Controls.ItemClickEventArgs;
var clickedItem = arg.ClickedItem;
var item = clickedItem as ItemsModel;
var dialog = new ItemsDialog();
dialog.DataContext = item;
dialog.ShowAsync();
}
This shows the dialog, and the content is displayed as expected. Now I'm trying to split my xaml into different templates and I'm trying to use a ContentControl to display the appropriate template. I've written a DataTemplateSelector to help choose the correct template, but now I cannot figure out the data binding for the ContentControl (see simplified version below).
<ContentDialog.Resources>
<UI:MyTemplateSelector x:Key="MyTemplateSelector"
Template1="{StaticResource Template1}"
Template2="{StaticResource Template2}"/>
<DataTemplate x:Key="Template1"/>
<DataTemplate x:Key="Template2"/>
</ContentDialog.Resources>
<StackPanel>
<ContentControl DataContext="{Binding}"
ContentTemplateSelector="{StaticResource MyTemplateSelector}"/>
</StackPanel>
When debugging into my ContentTemplateSelector, my binding is always null. I've tried various forms of the binding syntax with no luck. How do I properly set the DataContext of the ContentControl to that of the ContentDialog?
When debugging into my ContentTemplateSelector, my binding is always
null
You need to set data binding for the Content property of ContentControl control, see Remarks in MSDN:
The Content property of a ContentControl can be any type of object,
such as a string, a UIElement, or a DateTime. By default, when the
Content property is set to a UIElement, the UIElement is displayed in
the ContentControl. When Content is set to another type of object, a
string representation of the object is displayed in the
ContentControl.
So the following xaml should work:
<StackPanel>
<ContentControl Content="{Binding}"
ContentTemplateSelector="{StaticResource MyTemplateSelector}"/>
</StackPanel>
Check my completed sample in Github
You have to bind Content also.
Content="{Binding}"
You have the data source (DataContext) and how the data is displayed (templates) and now you need to specify which of the properties brings that together.
In JavaFX property can be bound to some observable value.
Label l = new Label();
l.visibleProperty().bind(l.textProperty().length().isEqualTo(3));
l.setText("123"); // show label
l.setText("1234"); // hide label
Recently I have discovered that binding can be done not only in code but in FXML markup document.
<!-- Label is visible only if input is visible. -->
<Label l="Please input some value:" visible="${value.visible}" />
<TextField fx:id="value" />
Is there similar feature in another languages and markup tools or that is kind of oracle innovation? :-)
update: I added XAML tag because I guess it has something similar.
I have found out that QML has the same feature.
I have search and tried a number of things to do this. I have a style that is successfully bound to multiple XAML frames by doing XAML code like this, the name of the style is ViewPersonTextboxDataStyle:
<TextBox Grid.Row="5" Grid.Column="1" Name="textboxName" Text="{Binding textboxName}" Margin="5,5,5,5" Style="{StaticResource ViewPersonTextboxDataStyle}"/>
So, when I get to another frame where I want to create the Grid rows and definitions in a code behind, I tried this, which I thought was correct:
var resourceDictionary = new ResourceDictionary()
{
Source = new Uri("ms-appx:///Common/StandardStyles.xaml", UriKind.Absolute)
};
var style = resourceDictionary["ViewPersonTextboxDataStyle"] as Style;
textBlock.Style = resourceDictionary["ViewPersonTextboxDataStyle"] as Style;
So at this point, I can see the style was found in the resource dictionary as style is populated correctly. But assigning into textBlock.Style causes a Catastrophic Exception. So, either I am missing a step or this is incorrect.
Not alot of net information on this.
Ok, thank you Raghavendra, this did point me in the right direction to tell me that things I was trying weren't off base.
What I ended up with is:
style = Application.Current.Resources["ViewPersonTextDataStyle"] as Style;
textBlock.Style = style;
Raghavendra is right, you don't need to use resource manager, and you also don't need to define it in the local XAML. I used the above line to do it by assigning current in every one of my frames anyway.
So with that, my exception was one for an IDIOT (namely me). I should have been using my TEXTBLOCK style not my TEXTBOX style. Assigning a textbox style to the textblock was causing the exception.
Try this:
textBlock.style = this.Resources["ViewPersonTextboxDataStyle"] as Style;
You need not use ResourceDictionary
Edit:
this.Resources refers to Page.Resources (that is in case the ViewPersonTextboxDataStyle is defined in Page.Resources we use this)
Try this one:
textBlock.style = App.Current.Resources["ViewPersonTextboxDataStyle"] as Style;
I have a component being called within a repeater. Within the call, i'm passing several variables to the component. All of them work fine except for one named totalSpan... which is returning a NaN for some reason. Here's the code I'm working with:
Parent:
<mx:Repeater id="indPositions" dataProvider="{projectPositions}" startingIndex="0" count="{projectPositions.length}">
<components:block height="28"
id="thisBlock" visible="true" horizontalScrollPolicy="off"
width="{projectWidth}"
oneDay="{Number(oneDay)}"
offSet="{indPositions.currentItem[0]}"
numDays="{indPositions.currentItem[1]}"
position="{indPositions.currentItem[2]}"
sName="{indPositions.currentItem[3]}"
projectName="{projectTitle}"
totalSpan="{Number(Math.round(projectWidth.vl / oneDay))}"
/>
</mx:Repeater>
All of the variables in there work fine and will typeof() just fine.
Here's the child code:
[Bindable] public var totalSpan:Number;
and then in the init() function I perform a simple:
Alert.show(String(totalSpan));
The alert returns "NaN".
On a semi-related note, i'm getting warnings on the following lines of the parent:
offSet="{indPositions.currentItem[0]}"
numDays="{indPositions.currentItem[1]}"
position="{indPositions.currentItem[2]}"
sName="{indPositions.currentItem[3]}"
with an message that says "Data binding will not be able to detect chances when using square bracket operator. For Array, please use ArrayCollection.getItemAt() instead.
Can anybody shed some light on these warning errors? an example would be greatly appreciated.
First of all the assignment of totalSpan is the following:
totalSpan="{Number(Math.round(projectWidth.vl / oneDay))}"
but from width="{projectWidth}" we can see projectWidth is a Number or int. So it hasn't vl property. And your Number(Math.round(projectWidth.vl / oneDay)) is NaN. Please rewrite it properly. Maybe it should be the following:
totalSpan="{Number(Math.round(projectWidth / oneDay))}"
About the second part. If you're using {} in MXML it stands for data binding. Data binding provides changes in target attributes with changes of source. And the message says Array is a primitive type and mxmlc compiler can't generate code for it to handle changes in array's values.
But it is obvious from code you have some problems with data structures. It is very hard to improve it do not having the whole project's code but you should use custom data types with required [Bindable] metadata for data binding and ArrayCollection instead of Array for data used as a source of data binding.
Try to create something like:
[Bindable]
class MyDataObject
{
public var offSet:int;
public var numDays:int;
public var position:int;
public var sName:String;
}
and put these items to data provider of your repeater. As far as I can understand now your data provider is for repeater length but in real life it should provide repeater elements data. So if you pass into your repeater an ArrayCollection of your custom MyDataObject objects you can use something like the following:
<mx:Repeater id="indPositions" dataProvider="{projectPositions}">
<components:block height="28"
id="thisBlock" visible="true" horizontalScrollPolicy="off"
width="{projectWidth}"
oneDay="{Number(oneDay)}"
offSet="{indPositions.currentItem.offSet}"
numDays="{indPositions.currentItem.numDays}"
position="{indPositions.currentItem.position}"
sName="{indPositions.currentItem.sName}"
projectName="{projectTitle}"
totalSpan="{Number(Math.round(projectWidth / oneDay))}"
/>
</mx:Repeater>
And even more. You can pass the whole object of MyDataObject type to your components:block component:
<mx:Repeater id="indPositions" dataProvider="{projectPositions}">
<components:block height="28"
id="thisBlock" visible="true" horizontalScrollPolicy="off"
width="{projectWidth}"
oneDay="{Number(oneDay)}"
myData="{MyDataObject(currentItem)}"
projectName="{projectTitle}"
totalSpan="{Number(Math.round(projectWidth / oneDay))}"
/>
</mx:Repeater>
Hope these thoughts help!