|
Well done for this reply. That was a mature and considered response, and I'd like to welcome you to Code Project.
|
|
|
|
|
Hello,
I am searching for inspiration ...
I'm currently building an business application using Silverlight.
To be honest, this is my first "proper" UI project in a long time, and I have had to do a lot of technology catchup - EF, MVVM, Prism, MEF/Unity - the list is endless - and I just hope that I'm on the right track ...
Part of the requirment is to enable the administrator to add custom defined fields the core entities within the application. these fields will change between customers - so it needs to be data driven. For example, a particular customer may have a requirement for certain bespoke finanacial fields on a Order header.
these custom fields would then be rendered at runtime into the SL page - and support all of the usual validation rules.
The sort of functionality I'm looking for is similar to the custom lists you get in sharepoint. I had considered using (or integrating into) sharepoint - but then this give me an added dependency that I did not want.
I am capabable of developing this whole framework myself, but before I dive-in, I thought I would ask to wider community if anyone is aware of any similar framework that would offer all (or part) of the functionality that I'm looking for.
Regards,
Gary.
|
|
|
|
|
Have you considered looking into Visual Studio Lightswitch? It sounds like it could be exactly what you want. See here[^].
|
|
|
|
|
I am using VS2008 and Silverlight 3. In a data form, I want to put some validation (like name can't be blank, age can't be <= 0)against save button. Error message will be display in a validation summary and textbox will marked by red.
Please help me.
|
|
|
|
|
|
I have a textblock and a slider* that are both bound to the same value of an object. The value actually represents a physical measurement coming from a device and it's nominally should be between 0 and 400. The problem is that the actual value read my go above or below that value (somewhere from about -5 to 450). This wasn't a problem in WPF, the slider just ignored values above and below the max and min, but in Silverlight it does something rather strange. It appears that if the value being bound to a slider goes above or below the max and min of the slider, the slider simply throws up it's hands (figuratively) and just stops binding. What gives? Is that normal behavior for the slider in Silverlight? I searched, but could find anything online that seems related.
I guess I could just have another property to my class that shadows the real value but caps it at the max and min of the slider, but that seems like an ugly hack around.
(* note: both are using one-way binding and are being used as indicators, not input controls - there are separate controls for that which have their own problems!)
|
|
|
|
|
i would add a binding converter to check and repairs the range if needed (IValueConverter)
or if that is over kill use a FallbackValue
|
|
|
|
|
Yes a converter is what I would go for too, assuming that the OP has already checked with a simple test example that the slider really is dropping the binding if it receives an invalid value.
|
|
|
|
|
Here's a simple test for you:
<UserControl x:Class="SLSliderDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local ="clr-namespace:SLSliderDemo"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<local:Data x:Key="data"/>
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot" Background="White" DataContext="{StaticResource data}">
<Slider Minimum="0" Maximum="10" Value="{Binding CurrentValue, Mode=OneWay}" IsEnabled="False"/>
<TextBlock Text="{Binding CurrentValue, StringFormat=Current Value \{0\}}"/>
<TextBox Text="{Binding CurrentValue, Mode=TwoWay}"/>
<TextBox/>
</StackPanel>
</UserControl>
And the data class:
namespace SLSliderDemo
{
public class Data : INotifyPropertyChanged
{
private double currentValue;
public double CurrentValue
{
get { return currentValue; }
set
{
currentValue = value;
OnPropertyChanged("CurrentValue");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
Run the demo - type 5 in the first text box. Slider moves half way, text block shows 5. Set the first text box to 7. Slider moves, text block shows 7. Set the first text box to 11. Slider moves to the end, text block shows 11. Set the first text box back to 2. Text block shows 2, slider is now stuck at 10.
|
|
|
|
|
Thanks. I think that would probably work. I did the shadow value thing, but I think a converter might be more MVVMish since I could abstract away from my MV worrying about what exactly the max and min values of the slider are. I could pass them as parameters instead.
Its just annoying that the Silverlight slider works that way. I guess it because of the lack of coercion support for dependency properties in Silverlight.
modified 30-Sep-11 16:09pm.
|
|
|
|
|
I had a working example of a combobox jumping to the correct selecteditem based on the choice of another combobox but I can't seem to make it work with a very simple example. I'll try to keep the code to a minimum but I don't see why a choice in "product" will not cause the correct "category" to be selected. This same code seemed to work fine when working with an EF data model based on the NW database.
Main window
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="1200">
<Grid Width="900" HorizontalAlignment="Left" DataContext="{Binding}">
<Grid.RowDefinitions>
<RowDefinition Height="44*" />
<RowDefinition Height="44*" />
<RowDefinition Height="44*" />
<RowDefinition Height="256*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="5,0,0,0" FlowDirection="LeftToRight" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" >
<TextBlock Text="Select a Product" Margin="5"></TextBlock>
<ComboBox Height="28" Name="cmbProducts2" Width="150" Margin="3"
IsEditable="False"
ItemsSource="{Binding Path=myProductList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding mySelectedProduct}"
>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Path=ProductName}" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Path=ProductID}" />
<TextBlock Text=") " />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ComboBox>
</StackPanel>
<StackPanel Grid.Row="1" Margin="5,0,0,0" FlowDirection="LeftToRight" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" >
<TextBlock Text="Category Should Auto Select" Margin="5"></TextBlock>
<ComboBox Height="28" Name="cmbCategory2" Width="150" Margin="3" IsEditable="False"
ItemsSource="{Binding Path=myCategoryList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding mySelectedCategory}"
>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Path=CategoryName}" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Path=CategoryID}" />
<TextBlock Text=") " />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ComboBox>
</StackPanel>
<StackPanel Grid.Row="2" Margin="5,0,0,0" FlowDirection="LeftToRight" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" >
<TextBlock Text="mySelectedCategory.CategoryName=" />
<TextBlock Text="{Binding mySelectedCategory.CategoryName}" Foreground="#FFFC0000"/>
<TextBlock Text=" mySelectedCategory.CategoryID=" />
<TextBlock Text="{Binding mySelectedCategory.CategoryID}" Foreground="#FFFC0000"/>
</StackPanel>
<StackPanel Grid.Row="3" Margin="5,0,0,0" FlowDirection="LeftToRight" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" >
<TextBlock Text="mySelectedProduct.myCategory.CategoryName=" />
<TextBlock Text="{Binding mySelectedProduct.myCategory.CategoryName}" Foreground="#FFFC0000" ForceCursor="True"></TextBlock>
<TextBlock Text=" mySelectedProduct.myCategory.CategoryID=" />
<TextBlock Text="{Binding mySelectedProduct.myCategory.CategoryID}" Foreground="#FFFC0000"/>
</StackPanel>
</Grid>
</Window>
Data repository
Imports System.Collections.ObjectModel
Public Class myDataRepository
Private _mycateorylist As ObservableCollection(Of myCategory)
Public Sub New()
_mycateorylist = New ObservableCollection(Of myCategory)
_mycateorylist = GetMyCategories()
End Sub
Public Function GetMyProducts() As ObservableCollection(Of myProduct)
Dim a As New myProduct()
Dim b As New myProduct
Dim c As New myProduct
Dim d As New myProduct
a.ProductID = 1
a.ProductName = "tire"
a.CategoryID = 1
b.ProductID = 2
b.ProductName = "wipers"
b.CategoryID = 1
c.ProductID = 3
c.ProductName = "tv"
c.CategoryID = 2
d.ProductID = 4
d.ProductName = "radio"
d.CategoryID = 2
Dim list As New List(Of myProduct)
list.Add(a)
list.Add(b)
list.Add(c)
list.Add(d)
Return New ObservableCollection(Of myProduct)(list)
End Function
Public Function GetMyCategories() As ObservableCollection(Of myCategory)
Dim a As New myCategory
Dim b As New myCategory
a.CategoryID = 1
a.CategoryName = "auto"
b.CategoryID = 2
b.CategoryName = "electronics"
Dim list As New List(Of myCategory)
list.Add(a)
list.Add(b)
Return New ObservableCollection(Of myCategory)(list)
End Function
Public Function GetMyCategory(ByVal id As Int32) As myCategory
Dim results = From c In _mycateorylist
Where c.CategoryID = id
Select c
Dim rs As IEnumerable(Of myCategory) = From x In results.AsEnumerable
Select New myCategory With
{
.CategoryID = x.CategoryID,
.CategoryName = x.CategoryName
}
Return rs.FirstOrDefault
End Function
End Class
Public Class myCategory
#Region "Primitive Properties"
Public Property CategoryID() As Global.System.Int32
Get
Return _CategoryID
End Get
Set(value As Global.System.Int32)
_CategoryID = value
End Set
End Property
Private _CategoryID As Global.System.Int32
Public Property CategoryName() As Global.System.String
Get
Return _CategoryName
End Get
Set(value As Global.System.String)
_CategoryName = value
End Set
End Property
Private _CategoryName As Global.System.String
#End Region
End Class
Public Class myProduct
#Region "Primitive Properties"
Public Property ProductID() As Global.System.Int32
Get
Return _ProductID
End Get
Set(value As Global.System.Int32)
_ProductID = value
End Set
End Property
Private _ProductID As Global.System.Int32
Public Property ProductName() As Global.System.String
Get
Return _ProductName
End Get
Set(value As Global.System.String)
_ProductName = value
End Set
End Property
Private _ProductName As Global.System.String
Public Property CategoryID() As Nullable(Of Global.System.Int32)
Get
Return _CategoryID
End Get
Set(value As Nullable(Of Global.System.Int32))
_CategoryID = value
End Set
End Property
Private _CategoryID As Nullable(Of Global.System.Int32)
Private _mycategory As myCategory
Public Property myCategory As myCategory
Get
Return _mycategory
End Get
Set(value As myCategory)
_mycategory = value
End Set
End Property
#End Region
End Class
View model
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Public Class MainWindowViewModel
Implements INotifyPropertyChanged
Public Property myProductList As ObservableCollection(Of myProduct)
Public Property myCategoryList As ObservableCollection(Of myCategory)
Private Property _context As myDataRepository
Public Sub New(ByVal db As myDataRepository)
_context = db
myProductList = _context.GetMyProducts()
myCategoryList = _context.GetMyCategories()
End Sub
Private Property _myselectedproduct As myProduct
Public Property mySelectedProduct As myProduct
Get
Return _myselectedproduct
End Get
Set(value As myProduct)
_myselectedproduct = value
mySelectedProduct.myCategory = _context.GetMyCategory(mySelectedProduct.CategoryID)
mySelectedCategory = mySelectedProduct.myCategory
OnPropertyChanged(mySelectedProduct, New System.ComponentModel.PropertyChangedEventArgs("mySelectedProduct"))
End Set
End Property
Private Property _myselectedcategory As myCategory
Public Property mySelectedCategory As myCategory
Get
Return _myselectedcategory
End Get
Set(value As myCategory)
_myselectedcategory = value
OnPropertyChanged(mySelectedCategory, New System.ComponentModel.PropertyChangedEventArgs("mySelectedCategory"))
End Set
End Property
#Region "INotifyPropertyChanged Members"
Private Sub OnPropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
Dim propertyName As String = e.PropertyName
Me.NotifyPropertyChanged(propertyName)
End Sub
Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(ByVal propertyName As String)
If Me.PropertyChangedEvent IsNot Nothing Then
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End If
End Sub
#End Region
End Class
|
|
|
|
|
Is the product actually changing in the ViewModel? Set a breakpoint and make sure. If not, you might want to add Mode=TwoWay,UpdateSourceTrigger=PropertyChanged to the SelectedItem bindings.
And on a related note, UpdateSourceTrigger=PropertyChanged is completely irrelevant on a OneWay binding, because the source never gets updated.
Binding modes:
* OneTime = Only changes when the DataContext is changed
* OneWay = This property updates from the source, but changes aren't sent back
* TwoWay = Updates in both directions
Unless you specifically mark the property as BindsTwoWayByDefault , you should assume it's OneWay by default.
|
|
|
|
|
The product is changing. I added the textblocks in the 2nd and 3rd grid rows to show the values of the properties as the combobox selection is made. I also put a break in and "mySelectedCategory" is updated when a choice is made to product.
I made a change to TwoWay and saw no difference.
My understanding of the binding modes matches what you have listed but I thought that UpdateSourceTrigger was still needed to let the viewmodel know that an update was made from the source. With OneWay I do indeed want to say that updates are not sent back, but UpdateSourceTrigger is there to let the view know that updates were made to the model.
|
|
|
|
|
Ah, Simon nailed the problem...
The category being dumped into "mySelectedCategory" isn't IN the list. It's an object created in GetMyCategory() that has the same values as one of the items in the list.
So the solution is to override the Equals() function of the category, so it returns true when the ID and Name match (Or just the ID). You'll also be told to override GetHashCode (Also a good idea)...
That way, the data binding system will be able to match "mySelectedCategory" to an item in the list, and select it for you.
|
|
|
|
|
You were correct and I posted my solution in the other post. I think I see the issue.
Regarding the statement that the category wasn't "in the list", given the common example displayed here, am I missing a better way to do this?
My assumption is your data layer will have functions to get a list of objects (for maybe a combobox) and also have a function to grab an object by ID. Are you implying that maybe my data layer should be doing something different for it's "get by id" type function? I'm all for learning a better method.
|
|
|
|
|
Well the trick is that you're not returning an item from the list of categories... You're returning an entirely different item with the same properties, when you do this:
Public Function GetMyCategory(ByVal id As Int32) As myCategory
Dim results = From c In _mycateorylist
Where c.CategoryID = id
Select c
Dim rs As IEnumerable(Of myCategory) = From x In results.AsEnumerable
Select New myCategory With
{
.CategoryID = x.CategoryID,
.CategoryName = x.CategoryName
}
Return rs.FirstOrDefault
End Function
If you just return results.FirstOrDefault , it'll give you the first result from the actual list. You're also doing the same thing with GetMyCategories() , by calling it once in the data model's constructor, and again in the view model's constructor, yielding two different collections with identical contents. The idea is to have one collection in the data model, give the view model a reference to that collection, and let the GUI bind to the view model's reference, so they all point to the same data.
|
|
|
|
|
Have a look at this article
Debugging WPF data bindings[^]
Hopefully it can help you debug your binding.
A quick tip, as myCategory does not override equals then mySelectedCategory will only be displayed/selected in the combobox if myCategoryList contain the very same reference.
My number one dev tool? Google
|
|
|
|
|
In a previous version I had tried that but it appears I coded it incorrectly. For some reason I tried to implement IEqualityComparer and when I did nothing changed. Instead I tried an override to Equals and it seems to have worked.
Sigh. I had the answer from a Google search a while back, I just implemented it incorrectly.
Here's what I coded that appears to have worked.
Public Overrides Function Equals(obj As Object) As Boolean
If IsNothing(obj) OrElse Not [GetType]().Equals(obj.GetType()) Then
Return False
End If
Dim myc As myCategory = CType(obj, myCategory)
Return CategoryID = myc.CategoryID
End Function
Public Overrides Function GetHashCode() As Integer
Return CategoryID.GetHashCode ^ CategoryName.GetHashCode
End Function
|
|
|
|
|
At first I reference http://blogs.msdn.com/b/jaimer/archive/2009/11/04/introduction-to-wpf-4-multitouch.aspx # 9931447 to implement multi-pen, but in the running, I found a noticeable delay between the touch point and the track, and using CPU resouces is very big.
In inkcanvas in writing when there is no such single issue.inkcanvas's static handwriting and dynamic handwriting is separate. In multi-pen implementation , how can I implement this effect?
public class Window2Panel : Panel
{
private VisualCollection _col;
public Window2Panel()
{
_col = new VisualCollection(this);
}
protected override Visual GetVisualChild(int index)
{
return _col[index];
}
protected override int VisualChildrenCount
{
get
{
return _col.Count;
}
}
bool down = false;
CustomPen pen=null;
protected override void OnMouseDown(MouseButtonEventArgs e)
{
down = true;
pen = new CustomPen(e.GetPosition(this));
_col.Add(pen);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (down && pen!=null)
{
pen.AddPoint(e.GetPosition(this));
}
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
down = false;
pen = null;
}
}
public class CustomPen : DrawingVisual
{
private Stroke stroke;
public CustomPen(Point point):this(new StylusPoint(point.X, point.Y))
{
}
public CustomPen(StylusPoint point)
{
StylusPointCollection points = new StylusPointCollection();
points.Add(point);
stroke = new Stroke(points);
}
public void AddPoint(Point point)
{
this.AddPoint(new StylusPoint(point.X, point.Y));
}
public void AddPoint(StylusPoint point)
{
stroke.StylusPoints.Add(point);
this.Draw();
}
private void Draw()
{
DrawingContext dc = this.RenderOpen();
stroke.Draw(dc);
dc.Close();
}
}
|
|
|
|
|
Here are two examples can be run, using VS2008 and. Net FrameWork3.0。
https://skydrive.live.com/redir.aspx?cid=8f125a6da8d15aee&resid=8F125A6DA8D15AEE!103
Delay example, the longer the draw, between the mouse and lines will be a very significant delay (after the mouse to stop, delay disappeared), and CPU utilization much, mainly because of the mouse each take a sampling point, we need to re-draw the lines;Non-delayed example you will find that handwriting is very smooth, although take up memory, but not as good as the first clear, the key is not that obvious delay.
My aim is to achieve multi-pen, refers to more than one person can use the stylus on the touch pad or finger free writing, which requires hardware support. Currently there is no hardware problem, the problem is a multi-pen when the delay is not significant (due to hardware limitations, there will be some delay in itself).
Examples of the use of delayed implementation, to achieve multi-pen, but the process caused the delay with the hardware itself, and do not make people suffer; example if the non-delay multiple ways to achieve freedom of writing, then, is an ideal, but I can not find how to DynamicRenderer the RootVisual simultaneously display different handwriting method.
What should I do here? how achieve multi-pen? Are there other ways? Please help me!
|
|
|
|
|
Hi,
How to get WM_Gesture/touch messages form windows 7 in WPF 4.0 touch aware application?
Currently I am only able to get Gesture notify message but not actual WM gesture message. but same we can get in win Forms.
|
|
|
|
|
Hi,
I work with WPF, and I have got a problem with binding a listbox.
The question is as follows.
I have a left list box of ten list box items. On the right hand I have a border where I can exchange between 10 User Controls.
So, I have a 10 listbox items for ten usercontrols. The problem is how to bind these 10 listitems and make them as a menu, so when I click on one of them I get the right User Control on the right side..
If ther is any solution, send please!
|
|
|
|
|
Thanks for your contribution and your funny comment in the bottom!
I have done exactly what you have there up! But the problem is in the collection. Because I have different VM for different Views, I couldn't create an instance of a collection.
Even if I have done an Array list, it would be difficult to determine/create and index that would return the right UserControl!
|
|
|
|
|
I have VS2010. Of the dozen plus examples and papers on WPF I have tried I find all are out of date. Some only need to be tweaked a little. Some are useless. It seems like WPF has really been a work in progress. It is not the author’s fault that Microsoft keeps changing things so much. Not even Microsoft's since they are trying to improve things and have lots of competitive pressures. It is just plain frustrating.
Sometimes the author provides info on the VS and .NET versions but not always. It is really helpful when they do.
Is there a way that after we get an example working in new version we could posted the updated source code with the article
|
|
|
|
|
Well, you could try the book in the post below. You can download the code for the examples in C#/WPF4 for VS2010 - everything is up-to-date. Just a suggestion.
It’s not because things are difficult that we do not dare, it’s because we do not dare that things are difficult. ~Seneca
|
|
|
|
|