I'm not getting EPiImage to show me the image when I use it in a Repeater.
If I move the resizer outside of the Repeater it works like a charm..
Is there anything special I need to think about?
<asp:Repeater ID="PageMenu" runat="server">
<HeaderTemplate>
<nav id="InlineSubNav">
<ul>
</HeaderTemplate>
<ItemTemplate>
<EPiImage:EPiImageResizer PropertyName="Image" Width="150" Height="150" Transformation="ScaleToFill" runat="server" />
<EPiServer:Property PropertyName="MainIntro" runat="server" />
<EPiServer:Property PropertyName="PageLink" runat="server" />
</ItemTemplate>
<FooterTemplate>
</ul>
</nav>
</FooterTemplate>
</asp:Repeater>
According to the source code for EPIImageResizer, the Render method will pick the property from another page, providing that the PageLink is set:
//If PageLink is set use that page instead of the current page
if (PageLink != PageReference.EmptyReference)
PageDataToUse = DataFactory.Instance.GetPage(PageLink);
if (PageDataToUse[PropertyName] != null)
{
ImageUrl = PageDataToUse[PropertyName].ToString();
So providing you are setting the PageLink property correctly, then there shouldn't be a problem.
Try using the binding syntax to populate the PageLink property within the ItemTemplate on the repeater, using something like this:
PageLink="<%# ((PageData)Container.DataItem).PageLink %>"
Alternatively set the value in the code behind by subscribing to the repeater's ItemDataBound event, retrieve the EPiImageResizer control using the e.Item.FindControl method and setting the PageLink using the value obtained from e.Item.DataItem.PageLink
As far I can see from the source code of EPiImage, it will not work/it's not supported.
You could try setting the PageLink property for each item.
In EPiImage 2.5 the issue with databinding was fixed.
by specifying the both PropertyName and PageLink attribute it now works
<EPiImage:EPiImageResizer PropertyName="Image" PageLink="<%# Container.CurrentPage.PageLink %>" Width="150" Height="150" Transformation="ScaleToFill" runat="server" />
Related
I am using a Combobox, in the controller the binding is done below and for some reason I need to delete few items from the Combobox So in onAfterRendering method I am removing the items as below.
this.byId("idaddrusages").removeItem(3);
The items were removed, however If I access the view in the same session it is throwing an error
Uncaught (in promise) Error: Error: adding element with duplicate id
'__xmlview0--container-component---newAddress--idNewAddUsagesItm-__xmlview0--container-component---newAddress--idAddressUsages-3'
If I refresh the page with a new session the items were removed from the Combobox.
View
<ComboBox id="idaddrusages" >
<core:Item id="idNewAddUsagesItm" key="" text=""/>
</ComboBox>
This is wrong way to declare combobox
<ComboBox id="idaddrusages" >
<core:Item id="idNewAddUsagesItm" key="" text=""/> // don't give id to item hence it complaints about duplicate id's
</ComboBox>
Secondly, better way to do is use local json model using your own defined json data or from odata model and bind the ComboBox as shown below
<ComboBox id="idaddrusages"
items="{
path: '/CollectionName'
}">
<core:Item key="{key}" text="{text}" />
</ComboBox>
Then you can remove items by just updating your model the way you like and combobox should be updated automatically
Let me know if it works for you.
DOM Manipulation is not working here n this case, hence we have removed the items from the model it self.
I have a listBox using an itemTemplate that contains the following line:
<Image Source="{Binding MyProperty.PossiblyNullObject.UrlProperty}"/>
Bound to this listBox is a model view collection that loads components of the items in the collection on a separate thread. The 'PossiblyNullObject' may not be set to a value when the xaml code is first rendered by the composition engine.
How does WPF handle this? Does it use a default value(no image source so no image) and continue on? Does it wait? Does it automatically detect when the value is initialized and rerenders with the new source? How does it not throw object null exceptions in the same way it would if I called 'MyProperty.PossiblyNullObject.UrlProperty' programmatically? How can I reproduce this functionality in my own code when I try to call it?
Thanks for any suggestions. I am embarrassingly new to WPF and I'm trying to tackle a problem out of my depth. The image load is a perf problem so I found a solution to load, decode, then freeze the image source on a background thread so it wouldn't lock up the UI. Unfortunately, I ran across this null exception problem when I tried replacing the image source binding with my solution that calls the same property. WPF somehow handles the possible null objects and I'd like to do it the same way to keep things clean.
In BindingBase have two properties: TargetNullValue and FallbackValue.
TargetNullValue returns your value when the value of the source is null.
FallbackValue returns your value when the binding is unable to return a value.
Example of using:
<!-- xmlns:sys="clr-namespace:System;assembly=mscorlib" -->
<Window.Resources>
<!-- Test data -->
<local:TestDataForImage x:Key="MyTestData" />
<!-- Image for FallbackValue -->
<sys:String x:Key="ErrorImage">pack://application:,,,/NotFound.png</sys:String>
<!-- Image for NULL value -->
<sys:String x:Key="NullImage">pack://application:,,,/NullImage.png</sys:String>
</Window.Resources>
<Grid DataContext="{StaticResource MyTestData}">
<Image Name="ImageNull"
Width="100"
Height="100"
Source="{Binding Path=NullString, TargetNullValue={StaticResource NullImage}}" />
<Image Name="ImageNotFound"
Width="100"
Height="100"
Source="{Binding Path=NotFoundString, FallbackValue={StaticResource ErrorImage}}" />
</Grid>
See this links, for more information:
BindingBase.TargetNullValue Property
BindingBase.FallbackValue Property
Note: The upvoted and accepted answer does not answer the question; it explains how you can get {Binding A} to work if A is null, which is trivial to handle anyway, but it does not explain what happens and how to handle the much more interesting case of {Binding A.B} when A is null, and that is specifically what the question is asking. What follows is the answer to the question as stated.
WPF generally handles the case where A is null when you use A.B in a binding; I have not tried specifically with <Image Source>, but I have tried with <DataGrid ItemsSource> and with <Button Command>.
When WPF handles these cases, what I have observed happening is that there is no error or warning in the output window, and the application malfunctions a bit, but it does not crash:
In the case of <DataGrid ItemsSource>, the DataGrid appears empty.
In the case of a <Button Command>, the button is clickable, but when you click it nothing happens.
In the case of <Image Source> I would expect that no image will appear.
(Note that all these are cases of silent failure, so whoever decided that WPF should behave this way should be shot by firing squad at the central square with great celebrations and live music and big giveaways.)
The way we generally handle these cases depends on the nature of the element at hand.
For images, if an empty image is acceptable, then you do not need to do anything. If some image must be shown despite the property being null, then the accepted answer probably provides a solution.
For grids, not showing anything when the property is null is probably the desired behavior.
For buttons, the solution is to use an additional binding to the IsEnabled property of the button.
So, for example:
<Button Command="{Binding A.B}" IsEnabled="{Binding HasA}"/>
Where HasA is defined in the viewmodel as follows:
bool HasA => A != null;
When I create (try to create) a ComboBox in WiX, the box receives its initial value from the corresponding property's value set earlier in the .wxs-file. This far, everythings goes as planned. When I try to change its value graphically, it displays no available list items. I have not found any necessary or relevant attributes etc in the docs that I haven't used, but also I'm quite noobish on WiX so maybe have missed something obvious. The code is below:
<Property Id="LANGUAGE" Value="Swedish" />
... cut ...
<Control Type="ComboBox" ComboList="yes" Property="LANGUAGE" Id="languages_combo" Width="..." Height="..." X="..." Y="...">
<ComboBox Property="LANGUAGE">
<ListItem Value="Swedish" />
<ListItem Value="English" />
</ComboBox>
</Control>
I want to be able to select "English" instead of "Swedish" in the drop-down, but that option is not available (and not "Swedish" for that matter - even that's the default value). Any suggestions how to solve this? I have searched the net without success, so I guess it's so basic no one has run into the same problem :-)
If it helps, here is the compilation:
candle test.wxs
light -ext WixUIExtension -sice:ICE20 test.wixobj
Attempts made by me:
Adding Text="..." to the ListItems does not help.
Replacing "ComboBox" with "ListBox" (and removeing attribute ComboList) displays the options/ListItems, but unfortunately ListBox is not the control that I want.
It's interesting when you make the same mistake over and over again, and never realize it's the good old mistake. I increased the Height attribute for Control, so the ListItems fit. Works like a charm!
I think you need to set the visible displayed text on the ListItems.
Try this:
<ComboBox Property="LANGUAGE">
<ListItem Text="English" Value="English" />
<ListItem Text="Swedish" Value="Swedish" />
</ComboBox>
Is there a way to bind to the instance of another control? Something like this:
<Button x:Name="Foo" Content="Foo" />
<local:CustomControl OtherControl="{Binding Foo}" />
I've tried setting DataContext to "this" in the constructor of MainPage but it doesn't seem to work.
CustomControl is defined something like this:
class CustomControl
{
public FrameworkElement OtherControl { get; set; }
}
Not sure what you trying to do but in Silverlight 3 you can use element binding to bind to a property on a control.
<Button x:Name="Foo" Content="Foo" />
<local:CustomControl x:Name="control" Property="{Binding Path=Content, ElementName=Foo}" />
In code you could always analyze the binding and get the element from that?
control.GetBindingExpression(Property).ParentBinding.Source
It is impossible in Silverlight 2:
Silverlight 2 doesn’t allow you to bind one element to another element. Instead, all bindings are to data
objects. (You could get around this using an intermediate object, but the added inconvenience means
it’s rarely worthwhile.)
<Button x:Name="Foo" Content="Foo" />
<local:CustomControl x:Name="control" OtherControl="{Binding ElementName=Foo}" />
I'd like an advice to the following problem: I want to embed a Button into a text flow, but when I embed a Button and Label (or TextBlock) into the WrapPanel, I get the first figure:
alt text http://sklad.tomaskafka.com/files/wpf-wrappanel-problem.png
I think that one of solutions could be FlowDocument, but I feel that this is far too heavy for a control simple like this (which could be used in several hundred instances). Do you have some other ideas about how to implement this? Thank you!
EDIT:
One solution could be the following (I didn't know it was possible to put more stuff into TextBlock), but I would lose the ability to bind (which I need):
<TextBlock TextWrapping="Wrap">
<Span>
<Button x:Name="MyButton" Command="{Binding Path=MyCommand}" Content="+" />
<Run x:Name="MyLabel" Text="{Binding Path=Subject}" />
<!--
Problem: binding makes following error:
A 'Binding' cannot be set on the 'Text' property of type 'Run'.
A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
-->
</Span>
</TextBlock>
To bind to Run.Text, checkout the BindableRun class by Fortes. Simple to implement, I use it all over my projects.
I found that implementing BindableRun correctly is pretty tricky - and almost all other available implementations will cause an exception from wpf layouting engine when the bound content changes from null to something non-null - see this problem, keyword "Collection was modified; enumeration operation may not execute."
Corrrect implementation from Microsoft is here - it shows how tricky this really is.
Solution: BindableRun class + the following markup:
<TextBlock>
<Button x:Name="MyButton" Command="{Binding Path=MyCommand}" Content="+" />
<common:BindableRun x:Name="Subject" BindableText="{Binding Path=Subject}"/>
</TextBlock>
Funny thing it works on the designer of a UserControl...
In that case, using the Property Change of your control to set the value to the Run is enough. I mean, if you had something like:
<TextBlock>
<Run Text="{Binding ElementName=thisCtrl, Path=Description}" />
</TextBlock>
Then just name the run, and on your property change handler of your UserControl DependencyProperty get/set the value.