|
hi,
It was great article.
I need something else maybe you can help me.
I need a list view with custom views like have in windows explorer (thumbnail,details,tile,icons).
I have a treeview which get it's data from WCF (and database) at every click it gets it's level and also a methos to get his childs for the list view but I was very complicated with le custom view of the listView.
As I mentioned, I need this to be in wpf and also it will be great having MVVM.
I get the data by WCF from the database means I have in the WPF browser application, services reference to my WCF.
I you need what I have done till now,I can upload it to a url you'll give me.
If you can help me'I'll be more that thankful.
|
|
|
|
|
This may be a frustrating question for some but I am new to all things .net and WPF. I have been working on a canvas project and came accross this one which has properties that would be very useful. I downloaded one of the demos (for DragCanvas) and it worked fine, but when I tried to make my own project and reference it, it would not work.
I tried to download these libraries but nothing I did was accepted, so I presume I was doing something wrong.
Any help would be appreciated,
thanks.
|
|
|
|
|
Hi Josh,
We have practiced MVVM pattern in our new project.
We have a general question regarding how to handle change things cross views.
There are two views.
The view1 includes the speed text box that allows user changes speed setting. If setting speed exceeds the maximum speed, viewmodel1 validation will display an error on view1.
View2 includes catalog selection. The catalog selection changes, the maximum speed may changes. Then we need to revalidation speed text box to ensure the setting speed still valid.
One way, we can implement this by using Event. When catalog changes, raise a catalog change event. Viewmodel1 registers this catalog change event and revalidate speed when catalog changes.
Is it a good way to use event in MVVM pattern in this case? Or we should avoid use event?
Thx!
|
|
|
|
|
|
WindowsFormsHost is UIElement. I add it to canvas and expected it works like other UIElement but it does not. It cannot be dragged. How to make it work?
<windowsformshost canvas.left="250" canvas.bottom="300">
<wf:listbox x:name="lstBox">
Thank you,
Haiping
|
|
|
|
|
My answer is no. When mouse goes over WindowsFormsHost the parent of the WindowsFormHost does not see the mouse events any more. So there is no way we can drag WindowsFormsHost inside canvas. I have done lots of searches these days. I could not find any example.
Please correct me if you think I am wrong. If you find an example please let me know.
|
|
|
|
|
I am tring to implement RaiseEvent for WindowsFormHost. It does not work either Can some body help me find out what I did wrong here:
// Create a custom routed event by first registering a RoutedEventID
// This event uses the bubbling routing strategy
public static readonly RoutedEvent WindowsFormsHostMouseDownEvent = EventManager.RegisterRoutedEvent("WindowsFormsHostMouseDown", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(WindowsFormsHost));
// Provide CLR accessors for the event
public event RoutedEventHandler WindowsFormsHostMouseDown
{
add { AddHandler(WindowsFormsHostMouseDownEvent, value); }
remove { RemoveHandler(WindowsFormsHostMouseDownEvent, value); }
}
private void lstBox_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(WindowsFormsHostMouseDownEvent, windowsFormHost);windowsFormHost.RaiseEvent(newEventArgs);
this.WindowsFormsHostMouseDown += new RoutedEventHandler(DragCanvasWindow_WindowsFormsHostMouseDown);
}
void DragCanvasWindow_WindowsFormsHostMouseDown(object sender, RoutedEventArgs e)
{
DragDrop.DoDragDrop(windowsFormHost, windowsFormHost, DragDropEffects.Move);
}
|
|
|
|
|
One would think that you would be able to add any visual element to the form and them inside the visual element events which are handling drag and drop would be sufficient to handle any element dragged and dropped onto its surface area.
This was if the element is another window you can at the very least render the target bitmap of the entire window and draw that inside the visual element. Then hooking the events in the new window to the visual element in the main window providing you a way to update them upon move or whatever other event you wanted...
|
|
|
|
|
Hi Josh,
We have a question regarding how to implement MVVM.
We have followed your article "WPF Apps With the Model-View-VieModel Design patter" to implement our prototype project.
So far we implement INotifyPropertyChanged in the viewmodel layer, we bind the viewmodel layer property with the UI control.
When the viewmodel layer property changes, we raise the OnPropertyChanged("TimeSetting "), UI control reflects the change right way.
Since the application will control a real instrument. We need propagate the change from model layer to UI layer. If model layer property changes, it will notify the viewmodel layer property and then update UI.
We implement INofityPropertyChanged in the model layer.
How do we implement Viewmodel to support this propagation?
Should we implement dependency properties in the Viewmodel layer and bind the model layer properties with Viewmodel's dependency properties? Or there is another way to do that?
We implement Viewmodel class to wrap a model class. All properties binding to UI is string properties for easy to do validation (following your article “Using ViewModel to Provide Meaningful Validation Error Messages”).
In the Model class,
public TimeSpan TimeSetting { get; set; }
In Viewmodel class,
public string TimeSetting
{ get {return timeSetText; }
set {
if (value == timeSetText)
return;
timeSetText = value;
this.OnPropertyChanged("TimeSetting");
}
}
we update model value during validaiton
string IDataErrorInfo.this[string propertyName]
{
get
{
if (propertyName == "TimeSetting")
{
string msg = this.ValidateTimeSet();
if (!string.IsNullOrEmpty(msg))
{
TimeSettingError = msg;
return msg;
}
// apply the time setting value now so that the runcondition object can also validate time vale
runConditions.TimeSetting = TimerUtility.StringToTimeSpan(timeSetText);
TimeSettingError =(runConditions as IDataErrorInfo)[propertyName];
return TimeSettingError;
}
Thanks!
|
|
|
|
|
The easiest way to do this is handle the PropertyChanged event of the Model object in the ViewModel, and switch(e.PropertyName) to raise the VM's PropertyChanged event for the corresponding bound property.
|
|
|
|
|
Josh, Thanks for the solution. It is an easy solution!
|
|
|
|
|
|
|
Attempting to use your implementation. I am afraid my requirements are making this difficult.
Couple things:
1. A CollectionViewSource and DataObjectProvider is used and the collection is populated outside the UI thread from another class. This class has the window (where we want to dnd) instance is passed to the constructor when it is instanciated so we can update the ObjectDataProvider (and others). On app start we send our an async request via this outside class, and when request is recieved via an event handler the DataObjectProvider ObjectInstance is set to the recieved data(after it is converted to the ObservableCollection of course).
2. CollectionViewSource is used as as follows:
<ObjectDataProvider x:Key="ObjectDataProviderCalls" />
<CollectionViewSource x:Key="CollectionViewSourceCalls" Source="{StaticResource ObjectDataProviderCalls}" >
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Ext" />
</CollectionViewSource.GroupDescriptions>
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription PropertyName="Id" Direction="Ascending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
Here is the exact error message:
Value cannot be null.
Parameter name: data
3. I attempted to create the ListViewDragDropManager when I set the DataObjectProvider's ObjectInstance (in the external thread), but received the "..you cannot update this object from this thread". I dont have the exact message, but also tried to put the ListViewDragDropManager instanciation code w/in a method w/in the Window and used Dispatcher.Invoke to call the code but didnt work.
Not sure if I am simple doing something wrong of if we need to modify this implementation to enable it to work w/in our context. I believe this to come down to threading (what fun).
TIA,
Steve
|
|
|
|
|
Hi Josh,
Thanks for posting this as a community resource - it's greatly appreciated!
I downloaded the source recently and noticed a problem with two of the RegexValidationRule constructors. It seems that the ErrorMessage property is not being set to the value of the errorMessage constructor parameter.
The original source code looks like:
public RegexValidationRule(string regexText, string errorMessage)
: this(regexText)
{
this.RegexOptions = regexOptions;
}
public RegexValidationRule(string regexText, string errorMessage, RegexOptions regexOptions)
: this(regexText)
{
this.RegexOptions = regexOptions;
}
When they probably should be:
public RegexValidationRule(string regexText, string errorMessage)
: this(regexText)
{
this.ErrorMessage = errorMessage;
}
public RegexValidationRule(string regexText, string errorMessage, RegexOptions regexOptions)
: this(regexText, errorMessage)
{
this.RegexOptions = regexOptions;
}
I've changed the assignment in the first constructor to set the ErrorMessage property instead of RegexOptions . I've also changed the second constructor to call the this(string, string) constructor overload instead of this(string) to ensure that the properties are set correctly.
I'm guessing this was a copy and paste error that snuck past the compiler because the regexOptions constructor parameter and the regexOptions backing store field use the same name.
I suppose that's another argument in favour of the convention that backing store fields for properties should be in camel-case prefixed with an underscore and parameters should just be camel-case.
Thanks again for an excellent resource!
Cheers,
John
|
|
|
|
|
Great catch, John! I'll update the source code with your fix as soon as I get a chance. Thanks!
|
|
|
|
|
My pleasure, Josh!
BTW, can I make a suggestion? Since I've modified my copy of the source code I took the liberty of adding another property to the regex validation rule.
I've added a boolean property called InvalidOnMatch, which allows me to decide whether the matching the regex is a good thing or a bad thing. I've used this for some situations where it's easier to write the regex to find bad data than it is to find good.
So, when InvalidOnMatch is false, the rule behaves as it would normally; when the value is true then it returns a ValidationResult.IsValid = false result if the regex matches successfuly.
If you're already touching the source code, do you think it'd be a worthwhile addition?
Cheers,
John
|
|
|
|
|
Definitely! That's a great addition. Thanks for letting me know about it.
|
|
|
|
|
Again, my pleasure!
If it saves you some time, let me copy the relevant changes here (I'm presuming the latest version of the framework, thus the auto-implemented property):
public bool InvalidOnMatch { get; set; }
And in the Validate method, I've modified the lines that check the regex to be:
if (!(Regex.IsMatch(text, this.RegexText, this.RegexOptions) ^ InvalidOnMatch))
result = new ValidationResult(false, this.ErrorMessage);
I've also modified the test project to be able to muck about with testing the InvalidOnMatch property. I've added a new combo box that let's you select a validation expression to use and a checkbox to set the InvalidOnMatch property (incidentally, this gives a nice example of how to bind to a validation rule in XAML).
My changes require that you add a string property called FreeFormText to the TestData.cs file. The complete updated XAML for the RegexValidatorWindow.xaml file is:
<Window x:Class="Test.RegexValidator.RegexValidatorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:jas="clr-namespace:WPF.JoshSmith.Controls.Validation;assembly=WPF.JoshSmith"
xmlns:local="clr-namespace:Test.RegexValidator"
Title="RegexValidator & RegexValidationRule Test" Height="341" Width="375"
FontSize="12"
>
<Window.Resources>
<!-- This validation rule is a static resource to demonstrate a technique for
binding to the properties of a regular expression -->
<jas:RegexValidationRule
x:Key="ProductCodeValidationRule"
RegexText="^[A-Z]{3}\.[0-9]{3}$"
ErrorMessage="Invalid product code. (Examples: ABC.123 xyz.789)"
RegexOptions="IgnoreCase"
/>
<!-- This style allows a validation error message to be
displayed in a TextBox's tooltip. -->
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="0,8" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding
RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent
}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Margin="4" VerticalAlignment="Center">
<TextBlock>E-mail Address:</TextBlock>
<TextBox
Text="{Binding Path=EmailAddress, UpdateSourceTrigger=PropertyChanged}"
jas:RegexValidator.RegexText="^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$"
jas:RegexValidator.ErrorMessage="Invalid e-mail address."
/>
<!-- Sets the RegexText attached property to a static property
which returns a localized regex, for the current date format. -->
<TextBlock>Localized Date:</TextBlock>
<TextBox
Text="{Binding Path=DateString, UpdateSourceTrigger=PropertyChanged}"
jas:RegexValidator.RegexText="{x:Static local:DateFormatRegex.DateRegex}"
jas:RegexValidator.ErrorMessage="Invalid date format."
/>
<!-- Explicitly creates a RegexValidationRule in order to set the RegexOptions. -->
<TextBlock>Product Code:</TextBlock>
<TextBox>
<TextBox.Text>
<Binding Path="ProductCode" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<jas:RegexValidationRule
RegexText="^[A-Z]{3}\.[0-9]{3}$"
ErrorMessage="Invalid product code. (Examples: ABC.123 xyz.789)"
RegexOptions="IgnoreCase"
/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<!-- Explicitly creates a RegexValidationRule in order to set the RegexOptions. -->
<TextBlock>Dynamic Regex:</TextBlock>
<ComboBox SelectedValue="{Binding Path=RegexText, Source={StaticResource ProductCodeValidationRule}}"
IsEditable="True" SelectedValuePath="Content" SelectedIndex="0">
<ComboBoxItem>(?#IP Address)^(?!0+\.0+\.0+\.0+$)(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)\.(2[0-4]\d|25[0-5]|[01]?\d\d?)$</ComboBoxItem>
<ComboBoxItem>(?#UK NI Number)^[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z]([ ]?\d{2}){3}[ ]?[A-D]?$</ComboBoxItem>
<ComboBoxItem>(?#Variable Names)^[a-zA-Z_][a-zA-Z_0-9]*</ComboBoxItem>
<ComboBoxItem>(?#String in quotes)"[^"\\]*(\\.[^"\\]*)*"</ComboBoxItem>
<ComboBoxItem>(?#Or write your own after this comment)</ComboBoxItem>
</ComboBox>
<CheckBox IsChecked="{Binding Path=InvalidOnMatch, Source={StaticResource ProductCodeValidationRule}}" Height="16" Width="120" HorizontalAlignment="Right">Invalid on match</CheckBox>
<TextBlock>Text to validate:</TextBlock>
<TextBox>
<TextBox.Text>
<Binding Path="FreeFormText" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<StaticResource ResourceKey="ProductCodeValidationRule"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
</Window>
Phew! That was an awful lot of stuff for a single post! If you want me to send you a zip file with all of the modifications, just let me know and we can swap email addresses.
Cheers,
John
|
|
|
|
|
Great work on all of these classes. I was just wondering if these changes still being planned to be included when you have the time? Thanks
|
|
|
|
|
Hey Josh,
I want to thank you for all your great articles here at Codeproject. I really enjoyed reading them!!! I am studying computer science at a university in germany and am trying to learn programming in WPF. When I started to learn the WPF, I read some books but finally ended up here at Codeproject, where I studied most of your articles.
About a year ago I had to do a project at my university and got stuck while programming many times. I searched the internet for answers (google), I looked into books - but I often found nothing until I looked in your articles. After my project at the university was over, a professor asked me how to learn the WPF - and I was able to tell him the best way to get started with Windows Presentation Foundation: Just read Mr. Smith's articles !!!
So thank you once again and please keep teaching us "The WPF Way"
- Simon
|
|
|
|
|
Wow! Thanks a lot Simon. I really appreciate that.
|
|
|
|
|
Hi Josh:
i need to do a multiple-row drag and drop in a list (reorder). Can you help me?
tks
smalcain
|
|
|
|
|
Thanks Josh! I am thinking about how I can use your UIElementAdorner
|
|
|
|
|