Если вы хотите избежать использования формы или ввода и ищете ссылку в виде кнопки, вы можете создать симпатичные ссылки для кнопки с оболочкой div, якорем и тегом h1
. Возможно, вы захотите этого, поэтому можете свободно размещать кнопку ссылки вокруг своей страницы. Это особенно полезно для горизонтальных центрирующих кнопок и имеющих вертикально центрированный текст внутри них. Вот как это делается:
Ваша кнопка будет состоять из трех вложенных частей: оболочки div, якоря и h1, например:
Тогда в CSS ваш стиль должен выглядеть вот так:
.link-button-wrapper {
width: 200px;
height: 40px;
box-shadow: inset 0px 1px 0px 0px #ffffff;
border-radius: 4px;
background-color: #097BC0;
box-shadow: 0px 2px 4px gray;
display: block;
border:1px solid #094BC0;
}
.link-button-wrapper > a {
display: inline-table;
cursor: pointer;
text-decoration: none;
height: 100%;
width:100%;
}
.link-button-wrapper > a > h1 {
margin: 0 auto;
display: table-cell;
vertical-align: middle;
color: #f7f8f8;
font-size: 18px;
font-family: cabinregular;
text-align: center;
}
Вот a jsFiddle , чтобы проверить его и поиграть с ним.
Преимущества этой настройки: 1. Создание отображения div-оболочки: блок облегчает центрирование (с помощью поля: 0 авто) и позиционирование (в то время как тег < a> встроен и его труднее позиционировать и невозможно центрировать).
Вы можете просто сделать < a> display: block, переместить его и стилизовать как кнопку, но тогда вертикальное выравнивание текста внутри него станет трудным.
Это позволяет вам использовать
Иногда, когда вы встраиваете < a> в элемент div, кликабелен только текст, эта настройка делает всю кнопку нажатой.
Вам не нужно иметь дело с формами, если вы просто пытаетесь перейти на другую страницу. Формы предназначены для ввода информации, и они должны быть зарезервированы для этого.
Позволяет вам аккуратно разделить стили кнопок и текста друг от друга (преимущество растягивания? Конечно, но CSS может выглядеть неприятно, поэтому его приятно разложить).
Это определенно упростило мою жизнь, создав мобильный сайт для экранов переменного размера.
Я пойду сверху (презентатор) и опишу отношения между участниками.
Презентатор получает объект службы через зависимость. Функциональность сервиса описана в его контракте:
class Presenter
{
public Presenter(IService service)
{
...
}
}
Реализация сервиса абстрагируется от конкретной реализации уровня доступа к данным. Обычно всякий раз, когда служба выполняет какое-либо действие, требующее взаимодействия с источником данных, она создает экземпляр единицы работы и удаляет ее по завершении.
interface IService
{
void Do();
}
class Service : IService
{
private readonly IUnitOfWorkFactory unitOfWorkFactory;
public Service(IUnitOfWorkFactory unitOfWorkFactory)
{
this.unitOfWorkFactory = unitOfWorkFactory;
}
public void Do()
{
// Whenever we need to perform some data manipulation we create and later dispose
// dispose unit of work abstraction. It is created through a factory to avoid
// dependency on particular implementation.
using(IUnitOfWork unitOfWork = this.unitOfWorkFactory.Create())
{
// Unit of work holds Entity Framework ObjectContext and thus it used
// create repositories and propagate them this ObjectContext to work with
IRepository repository = unitOfWork.Create<IRepository>();
repository.DoSomethingInDataSource();
// When we are done changes must be commited which basically means committing
// changes of the underlying object context.
unitOfWork.Commit();
}
}
}
/// <summary>
/// Represents factory of <see cref="IUnitOfWork"/> implementations.
/// </summary>
public interface IUnitOfWorkFactory
{
/// <summary>
/// Creates <see cref="IUnitOfWork"/> implementation instance.
/// </summary>
/// <returns>Created <see cref="IUnitOfWork"/> instance.</returns>
IUnitOfWork Create();
}
/// <summary>
/// Maintains a list of objects affected by a business transaction and coordinates the writing out of
/// changes and the resolution of concurrency problems.
/// </summary>
public interface IUnitOfWork : IDisposable
{
/// <summary>
/// Creates and initializes repository of the specified type.
/// </summary>
/// <typeparam name="TRepository">Type of repository to create.</typeparam>
/// <returns>Created instance of the repository.</returns>
/// <remarks>
/// Created repositories must not be cached for future use because once this
/// <see cref="IUnitOfWork"/> is disposed they won't be able to work properly.
/// </remarks>
TRepository Create<TRepository>();
/// <summary>
/// Commits changes made to this <see cref="IUnitOfWork"/>.
/// </summary>
void Commit();
}
/// <summary>
/// Represents factory of <see cref="UnitOfWork"/>s.
/// </summary>
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
private readonly IUnityContainer container;
/// <summary>
/// Initializes a new instance of the <see cref="UnitOfWorkFactory"/> class.
/// </summary>
/// <param name="container">
/// Dependency injection container instance used to manage creation of repositories
/// and entity translators.
/// </param>
public UnitOfWorkFactory(IUnityContainer container)
{
this.conainer = container;
}
/// <summary>
/// Creates <see cref="IUnitOfWork"/> implementation instance.
/// </summary>
/// <returns>Created <see cref="IUnitOfWork"/> instance.</returns>
public IUnitOfWork Create()
{
var unitOfWork = this.container.Resolve<UnitOfWork>();
unitOfWork.SetupObjectContext();
return unitOfWork;
}
... other members elidged for clarity
}
Реализация IUnitOfWork получает экземпляр IUnityContainer, а затем создает дочерний контейнер и регистрирует там экземпляр ObjectContext. Этот дочерний контейнер будет использоваться для создания репозиториев и распространения ObjectContext.
Вот упрощенная реализация IUnitOfWork:
class UnitOfWork : IUnitOfWork
{
private readonly IUnityContainer container;
private ObjectContext objectContext;
public UnitOfWork (IUnityContainer container)
{
this.container = container.CreateChildContainer();
}
public void SetupObjectContext()
{
this.objectContext = ... // Create object context here
this.container.RegisterInstance(context.GetType(), context);
}
public void Create<TRepository>()
{
// As long as we registered created object context instance in child container
// it will be available now to repositories during resolve
return this.container.Resolve<TRepository>();
}
public void Commit()
{
this.objectContext.SaveChanges();
}
}
class Repository : IRepository
{
private readonly SomeObjectContext objectContext;
public Repository(SomeObjectContext objectContext)
{
this.objectContext = objectContext;
}
public void DoSomethingInDataSource()
{
// You can use object context instance here to do the work
}
}