|
I don't see the point of a "link" (misuse).
It sounds like a "parent-child" relationship where the "selection" in the Parent listbox invokes a "subordinate" action.
Nothing about "linking".
Sounds like the "new view" (with the project) should have the "button" for the Quick Action.
"Disappearing" and "appearing" things is never a good idea; enabling / disabling is better (IMO). Less (re)orientating for the user.
I think a "context menu" right-click off your original selection is probably the most conventional / appreciated.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
|
Hi Kevin,
I know I am a little late to the party, haven't been visiting as much as I used to. However, I wasn't sure if you ever fixed your problem.
If I understand what your original question was, it would be that as you were on the treeviewitem the link would show but as soon as you moved to click on the link, the link would disappear.
I have created something similar in a project of mine. I think your trigger is set up correctly, however, I think it is your actual template that might be causing the problem.
I created a Grid much like yours, but instead of breaking it down in to columns I used a stack panel and set the orientation to horizontal. I think this makes the entire item one control instead of seeing two different entities inside of a grid. This allows for me to scroll over to my buttons without losing the trigger of the IsMouseOver.
as it stands
<HierarchicalDataTemplate>
<Grid>
<StackPanel Oreintation="Horizontal">
<TextBlock>
<MyButtonControl x:Name=Buttons Visibility="Hidden">
</StackPanel>
</Grid>
<HierarchicalDataTemplate.Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Buttons" Property="Visibility" Value="Visible"/>
</Trigger>
</HierarchicalDataTemplate.Trigger>
<HierarchicalDataTemplate>
As I pointed out we have set up the trigger the same, but my TreeviewItem.ItemTemplate was a little different than yours and this seems to work for me nicely. Hope it helps! Again, I know I'm a month late, but if this didn't help you, maybe it helps someone. Cheers.
|
|
|
|
|
I have a ScrollViewer with an ItemsSource that holds a user control. I need to know what the top visible item is in the scrollviewer at any given time, and I want my ViewModel to be able to react when the top item visible changes. I think that there is no built in functionality to do this, so perhaps I need to generate mouse down events in an attempt to select the topmost item, though I'd rather not have to do this.
here is the xaml for the top level stuff:
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" ScrollChanged="ScrollViewer_ScrollChanged">
<ItemsControl x:Name="DivisionItems" ItemsSource="{Binding oObsByDiv}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<uc:ucObservationsHeader/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
The ObservationHeader user control maps to a category for each set of observations, and is this:
<UserControl x:Class="MOATools.Views.ucObservationsHeader"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:uc="clr-namespace:MOATools.Views"
mc:Ignorable="d" d:DesignHeight="115" d:DesignWidth="400">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="300*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="100*"/>
</Grid.RowDefinitions>
<TextBox x:Name="divNum" Text="{Binding DivNum, Mode=OneWay}" Grid.Column="0" Grid.Row="0" Margin="0,3,0,0"/>
<TextBox x:Name="divName" Text="{Binding DivName, Mode=OneWay}" Grid.Column="1" Grid.Row="0" Margin="0,3,0,0"/>
<ItemsControl ItemsSource="{Binding lObs}" Grid.Row="1" Grid.Column="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<uc:ucObservationsView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
Each observation header then has a list of observations mapped to the ObservationsView:
<UserControl x:Class="MOATools.Views.ucObservationsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d" d:DesignHeight="75" d:DesignWidth="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="25*"/>
<RowDefinition Height="25*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".2*"/>
<ColumnDefinition Width=".4*"/>
<ColumnDefinition Width=".4*"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="txtDivObs" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{Binding obsFullNum, Mode=OneWay}" Grid.Column="0" Grid.Row="0"/>
<Label x:Name="lblOpenDate" HorizontalAlignment="Left" Content="Open " Grid.Column="1" Grid.Row="0"/>
<DatePicker x:Name="dtOpen" HorizontalAlignment="Right" SelectedDate="{Binding Opendate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.Row="0"/>
<Label x:Name="lblCLoseDate" HorizontalAlignment="Left" Content="Close " Grid.Column="2" Grid.Row="0"/>
<DatePicker x:Name="txtCloseDate" HorizontalAlignment="Right" SelectedDate="{Binding Closedate}" Grid.Column="2" Grid.Row="0"/>
<TextBox x:Name="txtDescription" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{Binding Description}" VerticalAlignment="Top" Grid.ColumnSpan="3" Grid.Row="1"/>
<TextBox x:Name="txtImagePath" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{Binding ImagePath}" Grid.Row="2" Grid.ColumnSpan="3">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding DataContext.PreviewImage, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
</Grid>
</UserControl>
What I want is that as the user scrolls through the categories and observations, each time a new observation category hits the top of the window then a combo box that is bound to a list of the categories to be set to that category. This will make it easy for the user to enter a new observation by defaulting to the current category that they see in the window. I don't want them to have to first select the header or an observation because extra clicks like that are just bad design. But I can't find any way for the view to know anything about the items that are scrolled into view. The scroll viewer can give me a vertical scroll position, but it's not really correlated to the actual parent and child items in the datastructure. Is this possible?
|
|
|
|
|
The convention is that you sync to the "selected item"; not any old item that "scrolls into view".
Without a "selected item", the user is guessing in terms of what is related to what (and so are you).
And simply "scrolling a list" (using the "thumb" for example) should NOT change the "selected item".
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Thanks Gerry, I do understand that using selected item is the convention, and I do that as well. This issue is a different case, and I have found a solution that works which is to use the Scroll event from the scroll viewer and test for the item containers to see if the render in the visible portion or not. This might be a convenience that only pertains to this use case, but it's interesting that WPF is flexible enough to allow for these things to work even if they aren't intended or preferred.
|
|
|
|
|
I am working on this app at home that I hope to sell as a nagware, i.e. completely free but display Ads for 10 seconds every time you save your work until the time you pay for it.
Now.. I have no idea how to display Ads in a WPF app.
I remember they had a whole section on it when I was doing Silverlight on the phone. But in WPF documentation there is nothing.
Any link / blog / API I should check? any other alternative idea?
After some googling I fear it might not be possible to display ads in WPF app (for legal / privacy reasons?)
How will one implement a nagware then?
I'd like user to have full power..
Oh well.. I might just have a 10 seconds count down (with no adds)... I guess that's a start...
modified 18-Dec-18 23:05pm.
|
|
|
|
|
The ads would come from an external web source presumably so you would just need to display a browser control in your nag screen and serve your ad there.
This space for rent
|
|
|
|
|
yeah.., all advertising thing I found seems to come from a website...
I haven't even started on the website yet and the app is not even alpha (yet).. mmm.. I guess it's too early to do anything about it...
|
|
|
|
|
You should conside UWP and the Microsoft Store, and a their "monetizing". You give up 30% on "games" and 10% on the rest. Reasonable "management" fees IMO.
Microsoft Ad Monetization platform
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
It's a good idea, but I checked many times and UWP is unfortunately a no no!
Why?
It's a document application! It needs to open file on your filesystem wherever they are. When it restart it automatically open previous document (like Visual Studio) and some important file can also be bookmarked for automatic usage of image resources.
All of that is night impossible with all the restriction to file system access that UWP apps suffer... I checked many times before
However you got a point. I think one can ship normal Desktop app in the store and have some hybrid UI (both WPF and UWP) so I might have a look.
Plus at this stage I have lot of WPF (not only XAML, but also low level custom Visual...) not sure how well it would port to UWP...
|
|
|
|
|
By "default", VS uses it's own "project folders".
If you expect to open "non-app" files on "start-up", you will need to "stage" this file locally after closing it on last use (your "MRU" list).
This needs to be done to maintain the security of the platform, and is reasonable if the user sticks with the "tool" as intended.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
I was looking at this blog post about WPF Data Validations.
It lays out some basic methods:
Data Annotations
This is nice because you can define model requirements on the model itself. HOW those requirements are enforced is done in whatever applications use those models.
IDataErrorInfo
In this case he invokes a service that does Server Side Validation. I can see this being useful for
things like checking for duplicates against a DB, bit not for simple UI validation like ensuring
required properties on a model are set.
But I can see uses for BOTH methods in an app. The annotations handle the simple, client side validation and the service handles more complex validation in the BL.
What I can't figure out is how to combine BOTH of these. I'd really like to have a generic assembly that I can re-use to handle validation.
Anyone know of a nice example?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
yes you can.
Below find my the base ModelBase class that I use, that uses data anntoation to validate its property when OnPropertyChanged() is fired, with caveat it uses my own attributes, and might be missing some stuff.. but it should give you an idea!
public abstract class ValidationAttribute : Attribute
{
public abstract void Validate(ModelBase model, FastMember member, object value);
public string ErrorMessage { get; set; }
}
public class ModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
{
#region INotifyPropertyChanged
public virtual void OnPropertyChanged([CallerMemberName]string name = "")
{
if (ValidatePropertyOnNotifyChanged)
{
if (string.IsNullOrEmpty(name))
{
Validate();
}
else
{
Validate(name);
}
}
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region ValidatePropertyOnNotifyChanged Validate()
public bool ValidatePropertyOnNotifyChanged
{
get { return mValidatePropertyOnNotifyChanged; }
set
{
if (value == mValidatePropertyOnNotifyChanged)
return;
mValidatePropertyOnNotifyChanged = value;
if (value)
Validate();
}
}
bool mValidatePropertyOnNotifyChanged;
public bool Validate()
{
ClearErrors();
foreach (var p in GetFastType().GetRuntimeMembers())
Validate(p);
return !HasErrors;
}
#endregion
#region Errors (databinding error friend)
public ErrorIndex Errors
{
get
{
if (eInfos == null)
eInfos = new ErrorIndex(this);
return eInfos;
}
}
ErrorIndex eInfos;
public class ErrorIndex : INotifyPropertyChanged
{
ModelBase model;
internal ErrorIndex(ModelBase model)
{
this.model = model;
}
public ErrorData this[string property]
{
get
{
var errs = model.GetErrors(property).Cast<object>();
return new ErrorData
{
HasError = errs.Any(),
Error = errs.FirstOrDefault(),
Errors = errs,
};
}
}
internal void Updated(string pName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pName)); }
public event PropertyChangedEventHandler PropertyChanged;
}
public class ErrorData
{
public bool HasError { get; set; }
public object Error { get; set; }
public System.Collections.IEnumerable Errors { get; set; }
}
#endregion
#region INotifyDataErrorInfo
List<Tuple<string, object>> errors
{
get
{
if (_errors == null)
_errors = new List<Tuple<string, object>>();
return _errors;
}
}
List<Tuple<string, object>> _errors;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
void RaiseErrorChanged(string pName)
{
pName = '[' + pName + ']';
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(pName));
OnPropertyChanged(nameof(HasErrors));
eInfos?.Updated(pName);
}
public System.Collections.IEnumerable GetErrors(string propertyName)
{
return errors.Where(x => x.Item1 == propertyName).Select(x => x.Item2);
}
public bool HasErrors { get { return errors.Count > 0; } }
public void UpdateErrors(string propertyName, params object[] errors) { UpdateErrors(propertyName, (IEnumerable<object>)errors); }
public void UpdateErrors(string propertyName, IEnumerable<object> errors)
{
bool had = false;
for (int i = this.errors.Count - 1; i >= 0; i--)
{
if (this.errors[i].Item1 == propertyName)
{
had = true;
this.errors.RemoveAt(i);
}
}
bool will = false;
if (errors != null)
{
errors.ForEach(x =>
{
will = true;
this.errors.Add(Tuple.Create(propertyName, x));
});
}
if (had || will)
{
RaiseErrorChanged(propertyName);
}
}
public void AddErrors(string propertyName, params object[] errors) { AddErrors(propertyName, (IEnumerable<object>)errors); }
public void AddErrors(string propertyName, IEnumerable<object> errors)
{
if (errors == null || errors.Count() == 0)
return;
errors.ForEach(x => this.errors.Add(Tuple.Create(propertyName, x)));
RaiseErrorChanged(propertyName);
}
public void ClearErrors(string propertyName)
{
int count = 0;
for (int i = errors.Count - 1; i >= 0; i--)
{
if (errors[i].Item1 == propertyName)
{
errors.RemoveAt(i);
count++;
}
}
if (count > 0)
RaiseErrorChanged(propertyName);
}
public void ClearErrors()
{
var names = errors.Select(x => x.Item1).Distinct().ToList();
errors.Clear();
names.ForEach(x => RaiseErrorChanged(x));
}
public bool Validate([CallerMemberName]string propertyName = null)
{
if (propertyName == null)
return Validate();
var m = GetFastType().GetRuntimeMembers().First(x => x.Name == propertyName);
ClearErrors(propertyName);
Validate(m);
return !GetErrors(propertyName).Cast<object>().Any();
}
FastType GetFastType() { return meType ?? (meType = FastType.GetType((GetType()))); }
FastType meType;
protected virtual void Validate(FastMember pi)
{
if (pi == null)
return;
var value = pi.GetValue(this);
var attrs = pi.GetAttributes().OfType<ValidationAttribute>();
foreach (var attr in attrs)
attr.Validate(this, pi, value);
}
#endregion
#region extra utilities: GetLazyCommand() AddWatch()
public DelegateCommand GetLazyCommand(Action onAction, [CallerMemberName]string name = null)
{
if (mCommands == null)
mCommands = new Dictionary<string, DelegateCommand>();
if (!mCommands.TryGetValue(name, out var result))
mCommands[name] = result = new DelegateCommand(onAction);
return result;
}
public DelegateCommand GetLazyCommand(Action<object> onAction, [CallerMemberName]string name = null)
{
if (mCommands == null)
mCommands = new Dictionary<string, DelegateCommand>();
if (!mCommands.TryGetValue(name, out var result))
mCommands[name] = result = new DelegateCommand(onAction);
return result;
}
public DelegateCommand GetLazyCommandAsync(Func<Task> onAction, [CallerMemberName]string name = null)
{
if (mCommands == null)
mCommands = new Dictionary<string, DelegateCommand>();
if (!mCommands.TryGetValue(name, out var result))
{
var cmd = new DelegateCommand();
cmd.Action = async (o) =>
{
try
{
cmd.IsEnabled = false;
await onAction();
}
finally { cmd.IsEnabled = true; }
};
mCommands[name] = result = cmd;
}
return result;
}
Dictionary<string, DelegateCommand> mCommands;
public void AddWatch<TP>(Expression<Func<TP>> e, Action<TP> onChange)
{
if (watchers == null)
watchers = new List<PropertyPath>();
var w = PropertyPath.Create(e);
watchers.Add(w);
w.PropertyChanged += delegate { onChange(w.Value); };
}
List<PropertyPath> watchers;
#endregion
}
|
|
|
|
|
Here's my two extension methods for checking if a property or an IDataErrorInfo object has any errors:
public static bool HasErrors( this IDataErrorInfo dataObject ) {
Type dataObjectType = dataObject.GetType();
PropertyInfo[] pInfo = dataObjectType.GetProperties( BindingFlags.Public | BindingFlags.Instance );
foreach ( PropertyInfo p in pInfo ) {
if ( p.CanWrite ) {
if ( string.IsNullOrEmpty( dataObject[ p.Name ] ) == false ) {
return true;
}
}
}
return false;
}
public static bool HasErrors( this IDataErrorInfo dataObject, string name ) {
if ( string.IsNullOrEmpty( dataObject[ name ] ) == false ) {
return true;
}
return false;
}
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
<DataGrid Grid.Column="1" x:Name="GrdInsCardsLookup" AutoGenerateColumns="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MaxWidth="600" Margin="3,6,3,-1" Background="{x:Null}">
<DataGrid.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFE22020" Offset="1"/>
</LinearGradientBrush>
</DataGrid.BorderBrush>
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Width="130" Binding="{Binding NationalId}"/>
<DataGridTextColumn Header="Name" Width="140" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Phone" Width="120" Binding="{Binding Phone}"/>
<DataGridTextColumn Header="City" Width="100" Binding="{Binding City}"/>
</DataGrid.Columns>
</DataGrid>
public class Instructer
{
public int Id { set; get; }
public string NationalId { set; get; }
public string Name { set; get; }
public string Fname { set; get; }
public string Lname { set; get; }
public string FatherName { set; get; }
public int Cityid { set; get; }
public string City { set; get; }
public string Address { set; get; }
public string Email { set; get; }
public string Phone { set; get; }
public string Mobile { set; get; }
public DateTime Birthday { set; get; }
public string Picid { set; get; }
public string Folder { set; get; }
}
public DataSet AllInsDataSet = new DataSet();
public List<Instructer> InstructersByName = new List<Instructer>();
private void FillInsList()
{
AllInsDataSet.Clear();
var con1 = new SqlConnection(Connectionstring);
SqlCommand cmd1;
cmd1 =
new SqlCommand(
"SELECT S1.[ins_id],S1.[ins_national_id],S1.[fname] as FName,S1.[father_name] as 'FatherName',S1.[lname] as 'LName',S1.[city_id],C1.[city],S1.[address],S1.[email],S1.[phone],S1.[mobile],S1.[birthday],S1.[pic_id],S1.[folder_id],S1.[other] FROM [DB_SchoolManager].[dbo].[tbl_ins_cards] S1 Inner Join [DB_SchoolManager].[dbo].[tbl_cities] C1 on S1.city_id=C1.city_id",
con1);
SqlDataAdapter da1;
da1 = new SqlDataAdapter(cmd1);
da1.Fill(AllInsDataSet);
}
private void FillLookupInsGrdByName(string name)
{
InstructersByName.Clear();
GrdStuCardsLookup.ItemsSource = InstructersByName;
string upname = name.ToUpper();
for (int i = 0; i < AllInsDataSet.Tables[0].Rows.Count; i++)
{
if (((AllInsDataSet.Tables[0].Rows[i][2] + " " + AllInsDataSet.Tables[0].Rows[i][3] + " " + AllInsDataSet.Tables[0].Rows[i][4]).ToUpper()).Contains(upname))
{
InstructersByName.Add(new Instructer()
{
Id = int.Parse(AllInsDataSet.Tables[0].Rows[i][0].ToString()),
NationalId = AllInsDataSet.Tables[0].Rows[i][1].ToString(),
Name = AllInsDataSet.Tables[0].Rows[i][2] + " " + AllInsDataSet.Tables[0].Rows[i][3] + " " + AllInsDataSet.Tables[0].Rows[i][4],
City = AllInsDataSet.Tables[0].Rows[i][6].ToString(),
Phone = AllInsDataSet.Tables[0].Rows[i][9].ToString(),
Picid = AllInsDataSet.Tables[0].Rows[i][12].ToString(),
Folder = AllInsDataSet.Tables[0].Rows[i][13].ToString()
});
}
}
GrdInsCardsLookup.ItemsSource = InstructersByName;
}
private void TxtSrchInsName_TextChanged(object sender, TextChangedEventArgs e)
{
if (!String.IsNullOrEmpty(TxtSrchInsName.Text))
{
SrchName = TxtSrchInsName.Text;
FillLookupInsGrdByName(SrchName);
}
}
|
|
|
|
|
so.. what is the exception you are getting?
From the look of it, it looks like you are binding to a list which has been updated after being given to the UI.
Hence the UI display the original list, that do not match the current list.
To solve that problem use a class implementing INotifyCollectionChanged . I recommend ObservableCollection<T> instead of List<T>
|
|
|
|
|
First thank you very much
i dont no the deference between List<t> and ObservableCollection<t> but it works
|
|
|
|
|
ObservableCollection<T> implements INotifyCollectionChanged
This is the interface that helps ListItem s synchronise with lists.
Glad it fixed your problem!
In visual studio, press "F12" when the cursor is on an unknown class and watch and learn!
"F1" will also be interesting if the class is part of Microsoft API...
|
|
|
|
|
You've posted the same question twice, and still managed to not provide the details of the exception.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
XML Code
<DataGrid Grid.Column="1" x:Name="GrdInsCardsLookup" AutoGenerateColumns="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MaxWidth="600" Margin="3,6,3,-1" Background="{x:Null}">
<DataGrid.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFE22020" Offset="1"/>
</LinearGradientBrush>
</DataGrid.BorderBrush>
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Width="130" Binding="{Binding NationalId}"/>
<DataGridTextColumn Header="Name" Width="140" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Phone" Width="120" Binding="{Binding Phone}"/>
<DataGridTextColumn Header="City" Width="100" Binding="{Binding City}"/>
</DataGrid.Columns>
</DataGrid>
C# Code
public DataSet AllInsDataSet = new DataSet();
public List<Instructer> InstructersByName = new List<Instructer>();
private void FillInsList()
{
AllInsDataSet.Clear();
var con1 = new SqlConnection(Connectionstring);
SqlCommand cmd1;
cmd1 =
new SqlCommand(
"SELECT S1.[ins_id],S1.[ins_national_id],S1.[fname] as FName,S1.[father_name] as 'FatherName',S1.[lname] as 'LName',S1.[city_id],C1.[city],S1.[address],S1.[email],S1.[phone],S1.[mobile],S1.[birthday],S1.[pic_id],S1.[folder_id],S1.[other] FROM [DB_SchoolManager].[dbo].[tbl_ins_cards] S1 Inner Join [DB_SchoolManager].[dbo].[tbl_cities] C1 on S1.city_id=C1.city_id",
con1);
SqlDataAdapter da1;
da1 = new SqlDataAdapter(cmd1);
da1.Fill(AllInsDataSet);
}
private void FillLookupInsGrdByName(string name)
{
InstructersByName.Clear();
GrdStuCardsLookup.ItemsSource = InstructersByName;
string upname = name.ToUpper();
for (int i = 0; i < AllInsDataSet.Tables[0].Rows.Count; i++)
{
if (((AllInsDataSet.Tables[0].Rows[i][2] + " " + AllInsDataSet.Tables[0].Rows[i][3] + " " + AllInsDataSet.Tables[0].Rows[i][4]).ToUpper()).Contains(upname))
{
InstructersByName.Add(new Instructer()
{
Id = int.Parse(AllInsDataSet.Tables[0].Rows[i][0].ToString()),
NationalId = AllInsDataSet.Tables[0].Rows[i][1].ToString(),
Name = AllInsDataSet.Tables[0].Rows[i][2] + " " + AllInsDataSet.Tables[0].Rows[i][3] + " " + AllInsDataSet.Tables[0].Rows[i][4],
City = AllInsDataSet.Tables[0].Rows[i][6].ToString(),
Phone = AllInsDataSet.Tables[0].Rows[i][9].ToString(),
Picid = AllInsDataSet.Tables[0].Rows[i][12].ToString(),
Folder = AllInsDataSet.Tables[0].Rows[i][13].ToString()
});
}
}
GrdInsCardsLookup.ItemsSource = InstructersByName;
}
public class Instructer
{
public int Id { set; get; }
public string NationalId { set; get; }
public string Name { set; get; }
public string Fname { set; get; }
public string Lname { set; get; }
public string FatherName { set; get; }
public int Cityid { set; get; }
public string City { set; get; }
public string Address { set; get; }
public string Email { set; get; }
public string Phone { set; get; }
public string Mobile { set; get; }
public DateTime Birthday { set; get; }
public string Picid { set; get; }
public string Folder { set; get; }
}
modified 16-Dec-18 7:53am.
|
|
|
|
|
My form has a ScrollViewer (horizontally oriented), with elements consisting of a set of UserControls. Basically layed out like this:
<ScrollViewer Name="TrackScroller" . . .
<Grid x:Name="TrackGrid" . . .
<Grid.ColumnDefinitions>
...
<local:TrackModule x: . . .
What I'd like to know, before I delve into it and possibly make myself crazy, is it possible to reorder the elements (the TrackModules) by dragging them to new positions in the grid? And, if so, will everything adjust itself afterward automatically?
Searching, I find tons of stuff about reordering DataGrid columns, but this isn't a DataGrid, and reordering rows of plain vanilla Grids, but nothing about columns.
Is what I'm thinking of doing even possible? (This is just a feature I'm idly thinking about, nothing even close to vital, so ROI is a factor, too.)
|
|
|
|
|
Normal panels are not quite friendly to drag operation (except perhaps canvas panel)
But I can imagine that one could create an adorner on mouse down, drag the adorner on mouse drag, update items Grid.Column on mouse up of the adorner
if you don't know about adorners:
Adorners Overview | Microsoft Docs
|
|
|
|
|
Thanks. I'll look into it.
|
|
|
|
|
Can someone show me how to create a Border with a background that pulsates from one color to another. I'm looking for a two-color fade in/out. The colors must be bound to property.
The colors will be set in response to a Status DP being changed.
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|