|
Thanks for the suggestion and yes he is using Photoshop. I will try using the tool you pointed to.
|
|
|
|
|
Hi there, I am getting an error in K2 Service Manager.
System.Exception: Datafield LINE MANAGERApprovals not found
at SourceCode.KO.DataFields.get_Item(String Index)
at SourceCode.KO.DataFields.get_Item(String Index)
at GenFunctions.GetSettings(ServerEventContext K2, Int32 FormTypeId)
at K2Code193479.Main(ServerEventContext K2)
Can you please tell me how to resolve this problem?
Thanks in advance,
Jhon.
|
|
|
|
|
Well, I would suggest that you might get a better answer on this site[^] which is dedicated to the software.
"WPF has many lovers. It's a veritable porn star!" - Josh Smith As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.
My blog | My articles | MoXAML PowerToys | Onyx
|
|
|
|
|
i have constructed a 3D object using WPF and i want to rotate that object. i also use the following code to rotate the object:
<Transform3DGroup>
<RotateTransform3D x:Name="rotate_center_x" CenterX="1" CenterY="0" CenterZ="0">
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="rotatex" Axis="1,0,0" Angle="0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
<RotateTransform3D x:Name="rotate_center_y" CenterX="0" CenterY="1" CenterZ="0">
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="rotatey" Axis="0,1,0" Angle="0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
<RotateTransform3D x:Name="rotate_center_z" CenterX="0" CenterY="0" CenterZ="1">
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="rotatez" Axis="0,0,1" Angle="0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
but the problem is, when i rotate the object for a certain angle in x, y and z axis, and come to x-axis again, it doesn't rotate the same direction as previous. you can see the similar types of scenario in the following link.
Click Here
may be here the object rotate along its local coordinate, not its world coordinate. how can i solve this problem?
|
|
|
|
|
Alright, here's what I've got. I have an IEnumerable collection of type <Person> containing some random info (name, age, etc). I create a PagedCollectionView using my <Person> collection and bind it to a DataGrid. Then I make a PropertyGroupDescription using the "Name" property of my <Person> object and voila, I've got a datagrid that is grouped by name.
////code for above///////////////
PagedCollectionView pagedCollectionView = new PagedCollectionView(Person.GetPeople(), true, false);
PersonDataGrid.ItemsSource = pagedCollectionView;
PropertyGroupDescription namePropertyGroupDescription = new PropertyGroupDescription("Name");
pagedCollectionView.GroupDescriptions.Add(namePropertyGroupDescription);
/////////////////////////////////
Now instead of just showing the name of the group and the number of items in the RowGroupHeader, I would like to show a DataGrid containing the 1st row of each group. Using this code:
<Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Center">
<data:DataGrid x:Name="PersonDataGrid" AutoGenerateColumns="False">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<data:DataGridTextColumn Header="Age" Binding="{Binding Age}" />
<data:DataGridTextColumn Header="Height" Binding="{Binding Height}" />
<data:DataGridTextColumn Header="Weight" Binding="{Binding Weight}" />
<data:DataGridTextColumn Header="Phone Number" Binding="{Binding Phone}" />
</data:DataGrid.Columns>
<data:DataGrid.RowGroupHeaderStyles>
<Style x:Name="DataGridRowGroupHeaderStyle" TargetType="data:DataGridRowGroupHeader">
<Setter Property="SublevelIndent" Value="0" />
<Setter Property="Height" Value="80" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<data:DataGrid AutoGenerateColumns="False" HeadersVisibility="None" ItemsSource="{Binding Items}">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<data:DataGridTextColumn Header="Age" Binding="{Binding Age}" />
<data:DataGridTextColumn Header="Height" Binding="{Binding Height}" />
<data:DataGridTextColumn Header="Weight" Binding="{Binding Weight}" />
<data:DataGridTextColumn Header="Phone Number" Binding="{Binding Phone}" />
</data:DataGrid.Columns>
</data:DataGrid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</data:DataGrid.RowGroupHeaderStyles>
</data:DataGrid>
</Grid>
I've got all of the items in the group showing up in the grid contained in the RowGroupHeader. Is there any way to just show the first row of each group in my RowGroupHeader? I've tried using a converter:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
List<Person> personList = (value as IEnumerable<Person>).ToList();
return new List<Person> { personList[0] };
}
but I can't get it to work properly. Any ideas?
|
|
|
|
|
C.J. wrote: <data:datagrid autogeneratecolumns="False" headersvisibility="None" itemssource="{Binding Items}">
Any luck with ItemsSource ="{Binding Items[0]} ?
There are only 10 types of people in this world — those who understand binary, and those who don't. |
|
|
|
|
|
Nope. I've been secretly hoping that it would be something easy like that, but alas. When I use Items[0] I get an empty grid.
|
|
|
|
|
I'm sorry - one more try (with the group)
data:DataGridTextColumn Header="Name" Binding="{Binding Name[0]}"
or
data:DataGridTextColumn Header="Name" Binding="{Binding Person[0].Name}"
In one scenario, I was able bind to a collection use something like myCollection[0].myProperty.
There are only 10 types of people in this world — those who understand binary, and those who don't. |
|
|
|
|
|
Cool. Thanks for your replies. I ended up using a converter, and the problem with my old converter was that I didn't include
<Grid.Resources>
<Common:GroupHeaderBinder x:Key="GroupHeaderBinder" />
</Grid.Resources>
in my code.
|
|
|
|
|
Hi all,
I have two questions about styling a datagrid.
1. I have a style for the combobox. Is it possible to apply the same style to my datagridcomboboxcolumn? Right now my datagridcomboboxcolumn looks like the default windows combobox.
2. How do I set the background of all column headers? I tried a lot, but if I resize my last column (on the right side) to the right and then back to the left, a standard grey header background is displayed at the right side of my last column. This grey header background does not belong to any column. It seems like there is a something like a column container which includes all columns.
Any help is apprechiated.
reibor.
|
|
|
|
|
1) Something like this perhaps?
<wpftk:DataGridComboBoxColumn EditingElementStyle="{StaticResource MyComboBoxstyle}" />
(or try ElementStyle=...)
2) Try setting the Width property on the last column to "*".
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I have a Silverlight 3.0 application which has the following:
listbox listbox grid (editContainer)
Customers Locations 3 comboboxes
2 textboxes
2 buttons
At startup the customer listbox is populated -- nothing else! At this point all of the controls in the editContainer are unaccessible...as if they are in a disabled state.
When a customer is selected the customer Locations list is populated, 2 comboboxes are populated. I've walked through this in debug mode and confirmed that the comboboxes are indeed getting data. The combo boxes are using code from another site that inherits the base silverlight code and adds the population logic when a database item has the key value instead of the text value in the combo box.
When I get the message that I can now edit data, everything in the editContainer is still in a disabled state. ComboBoxes don't drop down, cannot get my cursor entered into the textbox, and my buttons don't fire events. I initially thought it was because I added code to set the selected index on the combo boxes to -1, but even after commenting all that out I still have read-only controls.
here is the xaml:
<navigation:Page
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"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input"
xmlns:DatabaseManager_Silverlight_MasterService="clr-namespace:DatabaseManager.Silverlight.MasterService"
xmlns:DatabaseManager_Silverlight="clr-namespace:DatabaseManager.Silverlight"
xmlns:mycompany_Silverlight_Controls="clr-namespace:mycompany.Silverlight.Controls;assembly=mycompany.Silverlight.Controls"
x:Class="DatabaseManager.Silverlight.Views.ManageCustomerLocations"
d:DesignWidth="800" d:DesignHeight="600"
Title="ManageCustomerLocations Page">
<Grid x:Name="LayoutRoot" Background="#FFF8F8DE">
<Grid x:Name="editContainer" Margin="8,20,8,6">
<ListBox x:Name="customerList" HorizontalAlignment="Left" Margin="0,16,0,29" Width="183" SelectionChanged="CustomerSelectedEventHandler" DisplayMemberPath="CustomerName" />
<TextBox x:Name="message" Height="23" VerticalAlignment="Bottom" IsReadOnly="True" Text="{}{messages will appear here}" TextWrapping="Wrap"/>
<ListBox x:Name="customerLocations" HorizontalAlignment="Left" Margin="187,16,0,29" Width="100" SelectionChanged="CustomerLocationSelectedEventHandler" DisplayMemberPath="LocationID" />
<dataInput:Label HorizontalAlignment="Left" Margin="38,0,0,0" VerticalAlignment="Top" Width="72" Content="Customers" FontWeight="Bold" Foreground="#FF0D0D39" RenderTransformOrigin="1.153,0.562"/>
<dataInput:Label HorizontalAlignment="Left" Margin="204,0,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.567,1.562" Width="63" Content="Locations" FontWeight="Bold" Foreground="#FF0D0D39"/>
<Grid x:Name="locationContainer" Margin="291,16,0,29" IsHitTestVisible="False">
<Grid.DataContext>
<DatabaseManager_Silverlight_MasterService:CustomerLocation/>
</Grid.DataContext>
<Button x:Name="bmcKeyComputation" Margin="21,0,0,133" Content="Compute BMC Key" Click="ComputeBmcKeyEventHandler" Height="25" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="132"/>
<Button x:Name="submitChanges" Margin="21,0,31,65" VerticalAlignment="Bottom" Content="Create Location" Click="PostLocationEventHandler" ToolTipService.ToolTip="This button will create/update the location record."/>
<dataInput:Label HorizontalAlignment="Left" Margin="21,0,0,181" VerticalAlignment="Bottom" Content="Location Identity:" d:LayoutOverrides="HorizontalAlignment"/>
<TextBox x:Name="locationIdentity" HorizontalAlignment="Right" Margin="0,0,31,173" TextWrapping="Wrap" VerticalAlignment="Bottom" DataContext="{Binding LocationID, Mode=TwoWay, UpdateSourceTrigger=Explicit}" ToolTipService.ToolTip="This is the name for the location (office number, cage ID, etc)"/>
<TextBox x:Name="bmcKey" HorizontalAlignment="Right" Margin="0,0,31,134" TextWrapping="Wrap" VerticalAlignment="Bottom" DataContext="{Binding BmcLocKey, Mode=TwoWay, UpdateSourceTrigger=Explicit}" IsReadOnly="True" ToolTipService.ToolTip="The resulting BMC Key generated from the previous location data"/>
<dataInput:Label Height="20" VerticalAlignment="Top" Content="Building :" HorizontalAlignment="Left" Width="71" Margin="21,63,0,0"/>
<dataInput:Label Height="21" Margin="21,104,0,0" VerticalAlignment="Top" Content="Data Center :" HorizontalAlignment="Left" Width="80"/>
<dataInput:Label Height="19" Margin="21,146,0,0" VerticalAlignment="Top" Content="Location Type :" HorizontalAlignment="Left" Width="89"/>
<mycompany_Silverlight_Controls:ComboBoxClassic x:Name="buildingList" Margin="123,63,31,0" VerticalAlignment="Top" DisplayMemberPath="{Binding Building, Mode=TwoWay, UpdateSourceTrigger=Default}" ToolTipService.ToolTip="Identifies the starting point for this location"/>
<mycompany_Silverlight_Controls:ComboBoxClassic x:Name="dataCenterList" Margin="123,104,31,0" VerticalAlignment="Top" ToolTipService.ToolTip="Provides the secondary component of the location -- this changes based on 'building'" DataContext="{Binding DataCenter, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
<mycompany_Silverlight_Controls:ComboBoxClassic x:Name="locationTypeList" Margin="123,146,31,0" VerticalAlignment="Top" ToolTipService.ToolTip="For true datacenter locations, this is the type of location the customer contracted" DataContext="{Binding LocationType, Mode=TwoWay, UpdateSourceTrigger=Explicit}"/>
</Grid>
</Grid>
</Grid>
</navigation:Page>
It's alot of code, but here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using DatabaseManager.Silverlight.MasterService;
namespace DatabaseManager.Silverlight.Views
{
public partial class ManageCustomerLocations : Page
{
#region Page initialization logic
public ManageCustomerLocations( )
{
InitializeComponent( );
buildingList.DisplayMemberPath = "BuildingName";
buildingList.SelectedValuePath = "BuildingIdentity";
buildingList.BindingValidationError+=new EventHandler<ValidationErrorEventArgs>(buildingList_BindingValidationError);
dataCenterList.DisplayMemberPath = "DataCenterText";
dataCenterList.SelectedValuePath = "DataCenterIdentity";
dataCenterList.BindingValidationError+=new EventHandler<ValidationErrorEventArgs>(dataCenterList_BindingValidationError);
locationTypeList.DisplayMemberPath = "LocationName";
locationTypeList.SelectedValuePath = "LocationType";
locationTypeList.BindingValidationError+=new EventHandler<ValidationErrorEventArgs>(locationTypeList_BindingValidationError);
locationContainer.DataContext = new CustomerLocation( );
}
void locationTypeList_BindingValidationError( object sender, ValidationErrorEventArgs e )
{
MessageBox.Show( e.Error.Exception.Message );
}
void buildingList_BindingValidationError( object sender, ValidationErrorEventArgs e )
{
MessageBox.Show( e.Error.Exception.Message );
}
void dataCenterList_BindingValidationError( object sender, ValidationErrorEventArgs e )
{
MessageBox.Show( e.Error.Exception.Message );
}
bool InUpdateState = false;
protected override void OnNavigatedTo( NavigationEventArgs e )
{
PopulateCustomerList( );
}
private void PopulateCustomerList( )
{
DataReflectorClient client = new DataReflectorClient( );
client.OpenAsync( );
client.GetActiveCustomersCompleted += new EventHandler<GetActiveCustomersCompletedEventArgs>( ActiveCustomersEventHandler );
client.GetActiveCustomersAsync( );
client.CloseAsync( );
message.Text = "Loading active customers at this moment...please wait.";
}
#endregion
#region Database Completion Event Handlers
void GetCustomerLocationsCompletedEventHandler( object sender, GetCustomerLocationsCompletedEventArgs e )
{
customerLocations.ItemsSource = e.Result;
if ( e.Error != null )
SetWarningText( e.Error.Message );
else
SetEndingText( "Customer locations loaded successfully." );
customerLocations.UpdateLayout( );
}
void ActiveCustomersEventHandler( object sender, GetActiveCustomersCompletedEventArgs e )
{
this.customerList.ItemsSource = e.Result;
SetEndingText( "You may now choose the customer you want to work on." );
}
void GetLocationsCompleteEventHandler( object sender, GetLocationTypesCompletedEventArgs e )
{
locationTypeList.ItemsSource = e.Result;
SetEndingText( "Dropdown boxes populated." );
locationTypeList.UpdateLayout( );
}
void GetBuildingsCompleteEventHandler( object sender, GetBuildingEnumeratorsCompletedEventArgs e )
{
buildingList.ItemsSource = e.Result;
SetEndingText( "Dropdown boxes populated." );
buildingList.UpdateLayout( );
}
void LoadDataCenterEventHandler( object sender, GetDatacenterEnumeratorsCompletedEventArgs e )
{
dataCenterList.ItemsSource = e.Result;
SetEndingText( "You may now select which datacenter the customer location is at." );
dataCenterList.UpdateLayout( );
}
void HandleUpdateCompleteEventHandler( object sender, ManageCustomerLocationCompletedEventArgs e )
{
MessageResults results = e.Result as MessageResults;
if ( results == null )
SetWarningText( String.Format( "Unexpected result sent to completion event. Type of result was : {0}", e.Result.GetType( ).ToString( ) ) );
else if ( results.Status.Equals( 1 ) )
{
message.Text = String.Format( "Results: {0}", results.Message );
}
else
message.Text = String.Format( "Error: {0} Reason : {1}.....ooops.", results.ErrorMessage, results.Reason );
selectedLocation = null;
}
#endregion
#region Selection Event Handler Implementations
private void CustomerSelectedEventHandler( object sender, SelectionChangedEventArgs e )
{
customerLocations.ItemsSource = null;
if ( customerList.SelectedIndex < 0 )
{
return;
}
CustomerMaster master = customerList.SelectedItem as CustomerMaster;
if ( master == null )
{
SetWarningText( "There is a problem getting access to the selected customer." );
return;
}
DataReflectorClient client = new DataReflectorClient( );
client.OpenAsync( );
client.GetCustomerLocationsCompleted += new EventHandler<GetCustomerLocationsCompletedEventArgs>( GetCustomerLocationsCompletedEventHandler );
client.GetCustomerLocationsAsync( master.CustomerIdentity );
InUpdateState = false;
SetWarningText( "Populating dropdown boxes. Please wait...." );
client.GetBuildingEnumeratorsCompleted += new EventHandler<GetBuildingEnumeratorsCompletedEventArgs>( GetBuildingsCompleteEventHandler );
client.GetBuildingEnumeratorsAsync( );
client.GetLocationTypesCompleted += new EventHandler<GetLocationTypesCompletedEventArgs>( GetLocationsCompleteEventHandler );
client.GetLocationTypesAsync( );
client.CloseAsync( );
}
CustomerLocation selectedLocation = null;
private void CustomerLocationSelectedEventHandler( object sender, System.Windows.Controls.SelectionChangedEventArgs e )
{
if ( customerLocations.SelectedIndex < 0 )
{
}
else
{
InUpdateState = true;
selectedLocation = customerLocations.SelectedItem as CustomerLocation;
locationContainer.DataContext = selectedLocation;
SetEndingText( String.Format( "Chosen location {0} is now loaded into the editor.", selectedLocation.LocationID) );
}
}
private void BuildingSelectedEventHandler( object sender, SelectionChangedEventArgs e )
{
if ( buildingList.SelectedIndex < 0 ) return;
SetWarningText( "Getting the datacenter locations for selected building location." );
DataReflectorClient client = new DataReflectorClient( );
client.OpenAsync( );
client.GetDatacenterEnumeratorsCompleted += new EventHandler<GetDatacenterEnumeratorsCompletedEventArgs>( LoadDataCenterEventHandler );
client.GetDatacenterEnumeratorsAsync( ( ( BuildingEnumerator )buildingList.SelectedItem ).BuildingIdentity );
client.CloseAsync( );
}
private void DataCenterSelectedEventHandler( object sender, System.Windows.Controls.SelectionChangedEventArgs e )
{
if ( dataCenterList.SelectedIndex < 0 ) return;
SetEndingText( "You may now select the location type if applicable to this location." );
}
private void locationTypeList_SelectionChanged( object sender, SelectionChangedEventArgs e )
{
}
#endregion
#region Button Event handler implementations
private void ComputeBmcKeyEventHandler(object sender, System.Windows.RoutedEventArgs e)
{
message.Text = string.Empty;
BuildingEnumerator building = buildingList.SelectedItem as BuildingEnumerator;
if ( building == null )
message.Text = "You appear to have not selected a building yet. You need a building location to compute a BMC Key.";
else if ( locationIdentity.Text.Length.Equals( 0 ) )
message.Text = "You appear to have not provided a location name. Enter the location name before computing the BMC Key.";
else
bmcKey.Text = String.Concat( building.BuildingName.Substring( 0, 5 ), locationIdentity.Text );
}
private void PostLocationEventHandler(object sender, System.Windows.RoutedEventArgs e)
{
bool NoErrorsExist = true;
BuildingEnumerator building=null;
message.Text = string.Empty;
if ( buildingList.SelectedItem == null )
{
message.Text += "No building selected. ";
NoErrorsExist = false;
}
else
building = (BuildingEnumerator)buildingList.SelectedItem;
if ( dataCenterList.SelectedItem == null )
{
message.Text += "No data center selected. ";
NoErrorsExist = false;
}
if ( locationTypeList.SelectedItem==null && building != null && building.BuildingName != "Exacent" && building.BuildingName!="Office" )
{
message.Text += "No location type selected. ";
NoErrorsExist = false;
}
if ( locationIdentity.Text.Length.Equals( 0 ) )
{
message.Text = "No location name given. ";
NoErrorsExist = false;
}
if ( bmcKey.Text.Length.Equals( 0 ) && building != null && building.BuildingName != "Exacent" && building.BuildingName != "Office" )
{
message.Text = "BMC Key has not been generated. ";
NoErrorsExist = false;
}
if ( NoErrorsExist )
{
DataReflectorClient client = new DataReflectorClient( );
CustomerLocation newLocation = new CustomerLocation( );
if ( customerLocations.SelectedIndex > 0 )
newLocation = ( CustomerLocation )customerLocations.SelectedItem;
client.OpenAsync( );
if ( InUpdateState )
{
if ( newLocation.Building != ( ( BuildingEnumerator )buildingList.SelectedItem ).BuildingIdentity )
newLocation.Building = ( ( BuildingEnumerator )buildingList.SelectedItem ).BuildingIdentity;
if ( newLocation.DataCenter != ( ( DataCenterEnumerator )dataCenterList.SelectedItem ).DataCenterIdentity )
newLocation.DataCenter = ( ( DataCenterEnumerator )dataCenterList.SelectedItem ).DataCenterIdentity;
if ( newLocation.LocationType.HasValue && newLocation.LocationType.Value != ( ( LocationEnumerator )locationTypeList.SelectedItem ).LocationType )
newLocation.LocationType = ( ( LocationEnumerator )locationTypeList.SelectedItem ).LocationType;
if ( newLocation.LocationID != locationIdentity.Text )
newLocation.LocationID = locationIdentity.Text;
if ( newLocation.BmcLocKey != bmcKey.Text )
newLocation.BmcLocKey = bmcKey.Text;
client.ManageCustomerLocationCompleted += new EventHandler<ManageCustomerLocationCompletedEventArgs>( HandleUpdateCompleteEventHandler );
client.ManageCustomerLocationAsync( newLocation, RequestType.Update );
client.CloseAsync( );
}
else
{
CustomerLocation newlocation = new CustomerLocation();
newlocation.LocationIdentity = Guid.NewGuid( );
newlocation.CustomerIdentity = ( ( CustomerMaster )customerList.SelectedItem ).CustomerIdentity;
newlocation.Building = ( ( BuildingEnumerator )buildingList.SelectedItem ).BuildingIdentity;
newlocation.DataCenter = ( ( DataCenterEnumerator )dataCenterList.SelectedItem ).DataCenterIdentity;
newlocation.LocationType = locationTypeList.SelectedIndex >= 0 ? ( ( LocationEnumerator )locationTypeList.SelectedItem ).LocationType : new Nullable<int>( );
newlocation.LocationID = locationIdentity.Text;
newlocation.BmcLocKey = bmcKey.Text;
client.ManageCustomerLocationCompleted += new EventHandler<ManageCustomerLocationCompletedEventArgs>( HandleUpdateCompleteEventHandler );
client.ManageCustomerLocationAsync( newlocation, RequestType.Create );
client.CloseAsync( );
}
}
else
{
message.Text += "Please correct errors.";
return;
}
}
#endregion
void SetWarningText( string text )
{
SolidColorBrush brush = new SolidColorBrush( Colors.Red );
message.Foreground = brush;
message.Text = text;
}
void SetEndingText( string text )
{
SolidColorBrush brush = new SolidColorBrush( Colors.Black );
message.Foreground = brush;
message.Text = text;
}
}
}
|
|
|
|
|
Michael Eber wrote:
<Grid x:Name="locationContainer" Margin="291,16,0,29" IsHitTestVisible="False">
There's your problem right there.
IsHitTestVisible applies to the object and its children, and prevents it from responding to mouse events.
|
|
|
|
|
OMG! Thank you so much. I've been on app so long I'm seeing the forest and missing the trees.
You saved several more hours of hunting for this!!!
|
|
|
|
|
No problem
You stare at your own code for too long, you start to focus on some parts and disregard others... Then all it takes is a fresh pair of eyes to find the piece you ignored.
When I think I'm getting to this point, I usually hop on CP or /. for a bit to reboot the old brain.
|
|
|
|
|
|
|
Do you mean html page? Use javascript. Detailed info can be found at:
http://pietschsoft.com/post/2008/06/Silverlight-and-JavaScript-Interop-Basics.aspx
April
Comm100 - Leading Live Chat Software Provider
modified 27-May-14 21:45pm.
|
|
|
|
|
I have an object tree that has a few different objects types. For each of the object types, I would like them to be instantiated in a treeview with a custom element derived from the treeviewitem. Can someone give me a pointer for getting started with this approach?
I am aware of the simplicity of dealing with a treeview through an object model such as noted in this article[^]. However, this approach does not allow handling routed commands or creating command bindings. It also attaches a model object to a UI element, which complicates the application design if more than one UI element needs to refer to the model item. In my case, I really want the UI cleanly separated from the model. Again, some good pointers would be greatly appreciated.
|
|
|
|
|
Creating derived types for controls in WPF is usually a bad idea. Have you heard of DataTemplates or DataTemplateSelectors? You can use the former when you want to use a template according the the type of data (e.g., you can display class Cat differently than class Duck) and you can use the latter to select the template based on custom logic (e.g., if the name of the animal is "Alfred" or the previous animal was a Duck and the current one is a Dog, then display a particular template). I suggest you read Dr. WPF's Take on Data Templates.
|
|
|
|
|
I'm looking for information on a more specific issue than your largely unrelated response seems to recognize.
Yes, I am familar with templating, template seletors and what they can/cannot do. The article linked in the original posting and the specific issue of implementing routed command handlers within the individual treeviewitems illuminate the primary issue that I am trying to address. If you have suggestions on effective techniques to solve that sort of issue, your input will be warmly received.
With respect to blandly identifying good or bad approaches for UI development within WPF, I recommend that you review the "Control Authoring Overview" in MSDN. It specificially highlights when to write a new control and the capabities and limitations imposed by the level within the class heirarchy one chooses to base there development.
|
|
|
|
|
I can be more specific if you can be more specific. Here are some questions you can answer that may lead to more specific answers for you.
hb52134214 wrote: this approach does not allow handling routed commands or creating command bindings
Sure it does. Why wouldn't it? What are you trying to accomplish and what problems are you running into?
hb52134214 wrote: complicates the application design if more than one UI element needs to refer to the model item
Again, not sure I follow. Can you give an example of how multiple UI elements referring to the same model item complicates things? I'm envisioning a TextBlock and a TextBox binding to the same item... I don't see a problem with that.
hb52134214 wrote: I really want the UI cleanly separated from the model
Some people suggest MVVM. However, I never really have liked the concept of a view model. For more complex models (custom trees and such), rebuilding that as a view model seems like a lot of work. Sometimes, though, it is really easy to create a model and a view model. I personally don't stick to any particular design pattern religiously... I just try them and use them when I feel it's appropriate.
|
|
|
|
|
With regard to routed commands:
Lets say my application has two (bubbling) routed commands: SaveFile and SaveProject. The application also has a tree structure that represents a nested heirarchy of files and projects (and maybe other stuff as well). Lets say I have the following trivial heirarchical data templates (HDT):
<HDT x:Key="pItem" DT="{x:Type c:Project}" IS="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HDT>
<HTD x:Key="fItem" DT="{x:Type c:File}" IS="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HDT>
<HTD x:Key="other" DT="{x:Type c:Project}" IS="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HDT>
How does one attach a routed command handler in the template to get a node to respond to a SaveFile command. In anything else, I'd throw in the basic:
<CommandBindings>
<CommandBinding Command="{x:Static c:Cmds.SaveFile}" CanExecute="CanSave" Execute="Save"/>
</CommandBindings>
Unfortunately, I haven't been able to achieve this simple solution with a Heirarchical data template. Any suggestions?
On a side note, the ItemsControl (and thus TreeView & TreeViewItem) has a virtual function GetContainerForItemOverride, which allows one to return the container for their control, but unfortunately this call doesn't pass the object (or even the type) of object for which the container is being constructed. If it had, then it would be so trivial to implement a treeview that generates custom tree nodes without loosing any of the nice templating, styling or anything else. Too bad.
With regard to multiple UI elements refering to the same model item:
The link referenced in my original post showed how simple it is to use the model and have information update between the UI and the model. In the example, the author was searching for text in a tree. Because he linked the 'IsSelected' property of the TreeViewItem to a property (say 'ItemIsSelected' for clarity) in the model, he could walk the tree, and successively select each matching node in the search by merely setting the 'ItemIsSelected' property. Nice. I agree.
Now, throw that model into two separate trees and oops, setting the 'ItemIsSelected' causes both trees to change their selected item. Inorder to prevent that, but have that sort of functionality in both trees, one has to implement two properties in the model: 'ItemIsSelected_TV1', and 'ItemIsSelected_TV2' and in the different TreeView's.
The alternative is to use GetContainerFromElement. This technique more cleanly separates the UI and model, though I have to agree with the example's elegance (minus the resulting attachment to the UI).
|
|
|
|
|
On some further reflection, I could add the command bindings dynamically in the TreeView and TreeViewItem function 'PrepareContainerForItemOverride(DependencyObject obj, object item).' I'd prefer to put it in the template though, so if you do know how to do that, that would be much nicer.
|
|
|
|
|
hb52134214 wrote: How does one attach a routed command handler in the template to get a node to respond to a SaveFile command.
You could have a button inside the HDT. Set its Command to SaveFile and the CommandParameter to the current DataContext. The CommandParameter set to the current DataContext tells code later on which File was clicked. Then, add the CommandBinding to the TreeView's CommandBindings (or CommandBindings higher up).
hb52134214 wrote: one has to implement two properties in the model: 'ItemIsSelected_TV1', and 'ItemIsSelected_TV2' and in the different TreeView's
You could always make ItemIsSelected an array or list of booleans. Then, in your binding, you can reference it in the trees like this:
{Binding ItemIsSelected[0]}
{Binding ItemIsSelected[1]}
That way, you can use any number of trees without having to modify the view model. And if you don't want to fill in ItemIsSelected with a certain number of items in advance (say, 2 items), you could always create a custom collection (probably derived from IList) that fills in values if they do not already exist and returns a default the first time they are accessed. So, the following binding would cause 3 items to be in the collection:
{Binding ItemIsSelected[2]}
|
|
|
|
|