Silverlight DataGridColumn AttachedProperties - silverlight-3.0

I am attempting to create an AttachedProperty for a DataGridColumn within Silverlight 3.0 and I am having some issues.
Here is the AttachedProperty:
public class DataGridColumnHelper
{
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.RegisterAttached("Header", typeof(string), typeof(DataGridColumnHelper),
new PropertyMetadata(OnHeaderPropertyChanged));
private static void OnHeaderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
string header = GetHeader(d);
var dataGridColumn = d as DataGridColumn;
if (dataGridColumn == null)
{
return;
}
dataGridColumn.Header = GetHeader(dataGridColumn);
}
public static string GetHeader(DependencyObject obj)
{
return (string)obj.GetValue(HeaderProperty);
}
public static void SetHeader(DependencyObject obj, string value)
{
obj.SetValue(HeaderProperty, value);
}
}
As you can see it is really simple, I am trying to overcome the limitation that the Header Property in the DataGridColumn class cannot be bound.
This XAML works as expected...
<Controls:DataGridTextColumn Binding="{Binding OwnerName}"
HeaderStyle="{StaticResource DataGridColumnHeaderStyle}"
Behaviors:DataGridColumnHelper.Header="User Name"/>
However this XAML throws an error...(Specifically: {System.Windows.Markup.XamlParseException: AG_E_PARSER_PROPERTY_NOT_FOUND [Line: 224 Position: 112]
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
....})
<Controls:DataGridTextColumn Binding="{Binding OwnerName}"
HeaderStyle="{StaticResource DataGridColumnHeaderStyle}"
Behaviors:DataGridColumnHelper.Header="{Binding Resources.UserNameListViewHeading, Source={StaticResource Labels}}"/>
Just for experimentation I attached this property (with the binding syntax above) to a DataGrid and checked the DataGridColumnHelper.Header property in the OnHeaderPropertyChanged method and the value was correct (and an exception wasn't thrown)
It is my understanding that the object that the AttachedProperty is attached to must be a DependencyProperty. Looking through Reflector, DataGridColumn (from which DataGridTextColumn derives) derives from DependencyProperty.
Can somebody please shed some light on this? I am trying to Localize our application, and I am having trouble with the DataGrid. I am sure I can do this in code-behind, but I am trying to avoid that.

Chris, the problem is very simple, this won't work because the DataGridTextColumn is "detached" from the Visual Tree. Your DataGridTextColumn object is rooted in the Columns collection of the DataGrid - see the indirection. So even attached properties will not work as you expect. Now there is a way to make all this work using something I'm calling Attached Bindings, see:
http://www.orktane.com/Blog/post/2009/09/29/Introducing-nRouteToolkit-for-Silverlight-(Part-I).aspx
Just remember to attach the binding properties using something that is in the VisualTree (so the Grid holding the column would do just fine.)
Hope this helps.

Try using this, im assuming UserName is a property in your viewmodel
<Controls:DataGridTextColumn Binding="{Binding OwnerName}"
HeaderStyle="{StaticResource DataGridColumnHeaderStyle}"
Behaviors:DataGridColumnHelper.Header="{Binding UserName}"/>
I cant test your scenario so my post is just an idea. Might work, might not.

Related

AutoFixture constrained string parameter

Is there a simple way to specify a list of possible values for the parameter orderBy? Not one by one please, otherwise I would not be making the question. I want to specify that orderby makes sense only if it is chosen from a predetermined list. Suppose the list is very large...still not random. This cannot be that hard...no single example of such a simple task.
[Test, AutoData]
public override void IndexReturnsView(int? pageIndex, int? pageSize, string orderBy, bool? desc)
{
.....
}
EDIT:
All I want is to read the possible values from a list as I would do with the ValueSource attribute. However, it seems not to work with AutoFixture. If I specified e.g. [ValueSource("GetOrderByColumnNames")] my test does not work anymore. I have no idea of what I am doing wrong. Unfortunately AutoFixture lacks useful documentation and the examples are very basic. Is there a working example of this scenario that I can use to guide myself here?
This has to be a very common situation, however I have been looking for days with no luck :(.
Appreciated!
If I understand the question correctly, the problem is that the orderBy value should be randomly selected from a list of predefined values, but that list might be too large to use with [InlineAutoData].
The easiest way to do this that I can think of is to introduce a helper type. This might actually be a valuable addition to the application code itself, as it makes the role of various values more explicit, but if not, you can always add the wrapper type to the test code base.
Something like this is the minimum you'll need:
public class OrderCriterion
{
public OrderCriterion(string value)
{
Value = value;
}
public string Value { get; }
}
If we also imagine that this class exposes a list of ValidValues, you can implement an AutoFixture Customization using the ElementsBuilder class:
public class OrderCriterionCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new ElementsBuilder<OrderCriterion>(OrderCriterion.ValidValues));
}
}
Then you create a data source attribute for your test code base:
public class TestConventionsAttribute : AutoDataAttribute
{
public TestConventionsAttribute() : base(
() => new Fixture().Customize(new OrderCriterionCustomization()))
{
}
}
This enables you to write a test like this, which passes:
[Theory, TestConventions]
public void IndexReturnsView(
int? pageIndex,
int? pageSize,
OrderCriterion orderBy,
bool? desc)
{
Assert.Contains(orderBy.Value, OrderCriterion.ValidValues.Select(x => x.Value));
}
Notice that instead of declaring the orderBy parameter as a string, you declare it as an OrderCriterion, which means that AutoFixture will be detect its presence, and the Customization then kicks in.
See also https://stackoverflow.com/a/48903199/126014

HTML Extensions for wrapping other extensions

Most times when using DevEx MVC extensions, I find myself having to use repetitive code to generate the controls/layouts that I use on a regular basis. For example, I tend to prefer left-aligned captions to controls. Ideally, I'd be able to do something like this and have it "just work":
#Html.DevExpress().TextBoxFor(m => m.Notes).GetHtml()
However, in order to place the caption on the left, I need to also pass in a settings object for it, or dome something much more verbose such as:
#Html.DevExpress().TextBox(
s => {
// ...
s.Properties.CaptionCellStyle.Width = 100;
// ...
}
).Bind(Model.Notes).GetHtml()
What I thought to do was create my own set of extensions that would wrap the DevEx extensions, giving me some sort of common/core customization layer, so I could do something like this:
#Html.MyComponents().TextBoxFor(m => m.Notes)
This call would in turn call the DevExpress TextBoxExtension with a common set of settings and output the DevEx textbox as desired.
I've worked this up via custom html extensions (code below), but have two issues with this basic implementation:
The control renders at the very top of the Body element, not at the position in which it's placed in the view, and
There's a JavaScript error "ASPxClientTextBox" is not defined (this is part of the client-side scripting that DevEx uses with their controls).
I was hoping this would be an easy "wrap it and go" type of scenario. Is there some basic concept of these custom HTML extensions that I'm missing? Or does anyone know if this is a general limitation in trying to wrap another company's pre-existing extensions?
Here's the code I have implemented (which is not yet fully fleshed out, just trying for proof of concept here):
public static class HtmlHelpers
{
public static MyComponentsHtmlHelpers<TModel> MyComponents<TModel>(this HtmlHelper<TModel> html) {
return new MyComponentsHtmlHelpers<TModel>(html);
}
}
public class MyComponentsHtmlHelpers<TModel>
{
private HtmlHelper<TModel> html;
public MyComponentsHtmlHelpers(HtmlHelper<TModel> html) {
this.html = html;
}
public MvcHtmlString TextBoxFor<TValue>(Expression<Func<TModel, TValue>> expression) {
var data = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
string propertyName = data.PropertyName;
System.Diagnostics.Debug.WriteLine("PROPERTY NAME: " + propertyName);
TextBoxSettings s = new TextBoxSettings();
s.Name = "textbox_" + propertyName;
s.Properties.Caption = propertyName;
s.Properties.CaptionCellStyle.Width = 100;
TextBoxExtension tb = new TextBoxExtension(s);
return tb.GetHtml();
}
}
Nevermind - cleaning the solution and rebuilding as well as force refreshing the test browser a few times and ensure there's no cache and... now everything works as intended.
(not sure if I ought to delete this question or leave it around in case someone wants to attempt the same... I'll leave it for now, feel free to remove)

Role-based navigation display in MVC4 Bootstrap Sample

How are you supposed to conditionally display menu items based on roles in the Bootstrap Sample project? I was thinking of doing the following
Implement INavigatonRouteFilter - really just implementing the shouldRemove(Route navigationRoutes) method - by getting the default controller/action for the route and seeing if the user is authorized
Call NavigationRoutes.Filters.Add(myAuthorizationFilter) after configuring the NavigationRoutes in App_Start
There are two problems I see with this approach:
I don't actually know how to do the first step unless I add in a bunch of conditional statements to check for Controller's name explicitly
This seems like it could make NavigationRoutes.Filters very hard to deal with once there are a lot of filters or a desire for more modularity later on
I don't know that I've explained the problem clearly enough, but basically I want to use what is provided in the Bootstrap sample to implement authorization-based navigation menu display if at all possible. Using INavigationRouteFilter just seemed like the most natural way to do so.
For those looking for an answer or at least a quick fix.
Here's what I've come up with after 5 minutes and I most certainly haven't though about any side effects this may have.
routes.MapNavigationRoute<HomeController>("Index", c => c.Index())
.FilterRoute(() => !WebSecurity.IsAuthenticated);
You can either do all your filtering in your call to FilterRoute() or you can add more extension methods to save you some characters.
I'm thinking of .RequireRole("Adiministrators"); that calls WebSecurity.RequireRoles() in turn (or HttpContext.Current.User.IsInRole()) etc.
public static NavigationRouteBuilder FilterRoute(this NavigationRouteBuilder builder, Func<bool> func)
{
var currentRoute = builder._parent;
NavigationRoutes.Filters.Add(new BootstrapAuthorizationFilter(builder, x =>
{
if (x == currentRoute)
return func();
else
return false;
}));
return builder;
}
and BootstrapAuthorizationFilter is just a class implementing INavigationRouteFilter that calls func() in its ShouldRemove() method
public class BootstrapAuthorizationFilter : INavigationRouteFilter
{
private NavigationRouteBuilder builder;
private Func<NamedRoute, bool> func;
public BootstrapAuthorizationFilter(NavigationRouteBuilder builder, Func<NamedRoute, bool> func)
{
this.builder = builder;
this.func = func;
}
public bool ShouldRemove(Route navigationRoutes)
{
if (navigationRoutes is NamedRoute)
return func(navigationRoutes as NamedRoute);
return false;
}
}
Clearly nothing fancy and I'm not sure if I'd use it in production.
But I think is simple enough and works (for the cases I tested).
Having said that, I hope the new routing functionality is going to be released soon :)

How to clear SessionMap() in JSF without getting null in reference to this map

I use tomcat 7.0 and JSF 2.1 and I have problem when I call in my .xhtml page something like that: #{homePage.get("userName")}
I get javax.el.ELException: Caused by: java.lang.NullPointerException
at mainPacket.HomePageBean.get(HomePageBean.java:35)
I have ManagedBean like below:
#ManagedBean(name = "homePage")
#ViewScoped
public class HomePageBean {
private Map<String, Object> map;
public HomePageBean() {
map= FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
//remove unnecessary values from sessionMap
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().clear();
}
public String get(Object s){
return map.get(s).toString();
}
}
When I don't use clear, everything works ok. But I want to clear sessionMap. How to resolve it ?
Thanks
Java is an object oriented language. It doesn't give you a copy of the object everytime you request it. No, it gives you a reference to the object instance in memory. At the moment you invoke Map#clear() on the session map, then the map reference which you obtained just beforehand is basically also emptied, because it points to exactly the same map instance which you just emptied!
Your concrete functional requirement is nowhere mentioned in the question and the whole design in the code posted so far makes honestly no utter sense (I can't imagine any sensible real world use case for this), so it's hard to propose you the right solution. Best what you can get is the advice to add a nullcheck.
public String get(Object s){
Object value = map.get(s);
return (value != null) ? value.toString() : null;
}
You should by the way be very careful with abruptly emptying the session map this way. JSF stores view scoped and session scoped managed beans in there and it's also used by the flash scope.

How to return ArrayList type from DomainService Class to CLient Side?

Background: 3-4 weeks experience in Silverlight3/C#/.Net and about 3days worth with the RIA Services concept. (most of my previous questions up to date should explain why)
I am doing a test implementation of Microsoft's RIA services with Silverlight3. This is part of a proof of concept i have to do for a client. So its very basic.
I have figured out how build the Silverlight3 project using RIA services etc. So passing and returning strings and int's is no problem at the moment.
But i require to return an ArrayList from my Domain Service Class to my SL3 client. But it seems passing back an ArrayList as is, is not permitted. And my limited knowledge of C# does not aid in doing quick type casting/convertions/etc. This server-side function gets an ArrayList which must be returned to the SL3 client, so i have to do something with it to send it client side.
Question:
Does anyone know what should be done to an ArrayList (in c#) to allow a DomainService class function to return it to a calling client/SL3 function?
[NOTE: the majority of my attempts all end in the error: "Service operation named 'myFunctionName' does not conform to the required signature. Both return and parameter types must be an entity type or one of the predefined serializable types."]
Please feel free to request any information you feel would be appropriate.
Thank you in advance.
My apologies for not posting the solution i found. Bosses threw more work at me than i could handle. :)
Please note my solution may not be the best but since my knowledge in SL and RIA services are so new, i guess it may be excused. Initially i wanted to pass back rather complicated arrays from the code provided by our client, but effort and time restraints allowed me to only get it right to convert and return a List.
Hope this helps in some way.
Client Side : Silverlight Code in the MainPage.xaml.cs i have a call to retrieve a list of data from the server side, to display in a dropDown list.
// Function called on load of the SL interface
// 'slayer' is an object of the Domain Service Class server-side
// 'this.gidSessionNumber' is just a number used in the demo to represent a session
public void loadPaymentTypeComboBox()
{
InvokeOperation<IEnumerable<string>> comboList = sLayer.getPaymentTypeCombo(this.gidSessionNumber);
comboList.Completed += new EventHandler(popPaymentCombo_complete);
}//function loadAllComboBoxes
// Event handler assigned
public void popPaymentCombo_complete(object sender, EventArgs e)
{
InvokeOperation<IEnumerable<string>> obj = (InvokeOperation<IEnumerable<string>>)sender;
string[] list = obj.Value.ToArray();
// 'paymentTypeDropdown' is the name of the specific comboBox in the xaml file
paymentTypeDropdown.IsEnabled = true;
// Assign the returned arrayList as itemSource to the comboBox
paymentTypeDropdown.ItemsSource = list;
}
In the Domain Service Class i have the associated function:
[ServiceOperation]
public List<string> getPaymentTypeCombo(string gidNumber)
{
// Build objects from libraries provided by our client
SDT.Life.LifeCO.clsSystemCreator.CreateSysObjects(gidNumber);
this.lobjSys = SDT.Life.LifeCO.clsSystemCreator.GetSysObject(gidNumber);
// Rtrieve the ArrayList from the client's code
clsTextList comboList= this.lobjSys.lstPaymentType_PaymentQueue;
// Get the length of the returned list
int cnt= (int)comboList.Count();
// Create the List<string> which will be populated and returned
List<string> theList= new List<string>();
// Copy each element from the clsTextList to the List<string>
for (int i = 0; i < cnt;i++)
{
string status= comboList.Item(i).Description;
theList.Add(status);
}
// return the newly populated List<string>
return theList;
}//end function getPaymentTypeCombo
Not sure that you can return an ArrayList. I guess you should think about returning an IEnumerable instead which will make the service recognize the method as a Read method.
If you have a List or ObservableCollection and wish to bind it to an ItemControl like ComboBox, you can set the ItemsSource on your ItemControl. Use the DisplayPath property on the ItemControl to set the property you wish to display or use a DataTemplate.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text={"Binding Path=Property1"}/>
<TextBlock Text={"Binding Path=Property2"}/>
<TextBlock Text={"Binding Path=Property3"}/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Resources