I just recently started learning MVVM. I hope that a solution to this problem will come.
In my application, the user is authorized in the system, after which a window with a table opens. Users are divided into roles: Administrator and Employee. I want the Employee to be unable to see a certain column (ID).
I have an AuthorizationMeth
class, where the IDRoleAuthorization
variable stores role ID of the authorized user. How can I now use this value to hide the column ID? In my case if IDRoleAuthorization = 2
to hide column ID
Found solutions using the Freezable
class and creating a FrameworkElement
in XAML but I can't figure out how this is solved for my problem.
Methods/AuthorizationMeth.cs
public class AuthorizationMeth
{
public static int IDRoleAuthorization;
public bool Enter(string login, string password)
{
Intis6Context db = new Intis6Context();
if (login == "" || password == "")
{
MessageBox.Show("You have not completed all fields", "Authorization", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
var auth_check = db.Users.AsNoTracking().FirstOrDefault(ch => ch.Login == login && ch.Password == password);
if (auth_check == null)
{
MessageBox.Show("Login or password entered incorrectly", "Authorization", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
IDRoleAuthorization = auth_check.IdRole;
return true;
}
}
View/ContractView.xaml
<DataGrid Background="White" AutoGenerateColumns="False" EnableColumnVirtualization="True" EnableRowVirtualization="True"
ItemsSource="{Binding AllContrsupl_saleDTO, IsAsync=True}"
Grid.Row="0">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Path=Cnssid}"/>
<DataGridTextColumn Header="Author" Binding="{Binding Path=FULLNAMEstaff}"/>
<DataGridTextColumn Header="Type" Binding="{Binding Path=typeTable}"/>
CodePudding user response:
Have you tried something like this?
If you want to Hide the "ID" column try this:
You need to assign a x:Name to your DataGrid control first. For example "myDataGrid" Then you can do this in Code behind.
if(IDRoleAuthorization == 2)
{
myDataGrid.Columns[0].Visibility = Visibility.Collapsed;
}
Hope this helps.
CodePudding user response:
Don't expose a public static int IDRoleAuthorization
field. Such a field must be a property (never define public fields) and at least read-only, and a read-only instance property (non-static) at best. Additionally, don't expose the numeric value, but a bool
property e.g., IsAuthorized
. The logic to determine whether the numeric code evaluates to an authorized user must be encapsulated and not spread across the application. External classes must depend on the result of this evaluation only.
The DataGridColumn
definitions are not part of the visual tree. They are not rendered. they are just placeholders that contain information about the column, which will be generated by the DataGrid
later. The actual column consists of a DataGridColumnHeader
and DataGridCell
elements.
Because of this, you can't configure a Binding
on the DataGridColumn.Visbility
property.
You can now simply toggle the cells and their associated header (which will not remove the column, but the values of the header and cells):
<!-- ToggleButton to simulate the IsAuthorized property -->
<ToggleButton x:Name="ToggleButton" Content="Hide/show column content" />
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Dynamic Column">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ToggleButton, Path=IsChecked}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ToggleButton, Path=IsChecked}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Static Column" />
</DataGrid.Columns>
</DataGrid>
To remove the column completely in your scenario (no auto-generated columns), you must remove it manually from the DataGrid.Columns
collection or toggle the column definitions Visibilty
explicitly (by accessing the DataGrid.Columns
).
Add and AuthorizationChanged event to your view model class and make the view listen to it. In the event handler set the columns visibility or remove/add the column. Alternatively, write a simple attached behavior:
DataGridHelper.cs
class DataGridHelper : DependencyObject
{
public static string GetHidableColumnIndices(DependencyObject attachingElement) => (string)attachingElement.GetValue(HidableColumnIndicesProperty);
public static void SetHidableColumnIndices(DependencyObject attachingElement, string value) => attachingElement.SetValue(HidableColumnIndicesProperty, value);
public static readonly DependencyProperty HidableColumnIndicesProperty = DependencyProperty.RegisterAttached(
"HidableColumnIndices",
typeof(string),
typeof(DataGridHelper),
new PropertyMetadata(default(string), OnHidableColumnIndicesChanged));
public static Visibility GetColumnVisibility(DependencyObject attachingElement) => (Visibility)attachingElement.GetValue(ColumnVisibilityProperty);
public static void SetColumnVisibility(DependencyObject attachingElement, Visibility value) => attachingElement.SetValue(ColumnVisibilityProperty, value);
public static readonly DependencyProperty ColumnVisibilityProperty = DependencyProperty.RegisterAttached(
"ColumnVisibility",
typeof(Visibility),
typeof(DataGridHelper),
new PropertyMetadata(default(Visibility), OnColumnVisibilityChanged));
private static void OnColumnVisibilityChanged(DependencyObject attachingElement, DependencyPropertyChangedEventArgs e)
{
if (attachingElement is not DataGrid dataGrid)
{
throw new ArgumentException("Attaching element must be of type DataGrid.");
}
ToggleColumnVisibility(dataGrid);
}
private static void OnHidableColumnIndicesChanged(DependencyObject attachingElement, DependencyPropertyChangedEventArgs e)
{
if (attachingElement is not DataGrid dataGrid)
{
throw new ArgumentException("Attaching element must be of type DataGrid.");
}
ToggleColumnVisibility(dataGrid);
}
private static void ToggleColumnVisibility(DataGrid dataGrid)
{
IEnumerable<int> columnIndices = GetHidableColumnIndices(dataGrid)
.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(numericChar => int.Parse(numericChar));
foreach (int columnIndex in columnIndices)
{
dataGrid.Columns[columnIndex].Visibility = GetColumnVisibility(dataGrid);
}
}
}
Usage example
<DataGrid DatGridHelper.HidableColumnIndices="0,3,8"
DataGridHelper.ColumnVisiblility="{Binding IsAuthenticated, Converter={StaticResource BooleanToVisibilityConverter}}" />